diff --git a/DEPS b/DEPS
index 6929ccdc..80af83bf 100644
--- a/DEPS
+++ b/DEPS
@@ -175,11 +175,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': '3150d88ba4ca076d7072bdc59502cfee2c0fc666',
+  'skia_revision': '68219bfacaa82884cc34815b2cc43966fa0f3c31',
   # 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': '2f3157bad0b2280605ed2dce1489b44ae8987bc6',
+  'v8_revision': '5dcf1b6646d1bf03d21883dd1413bd56493dc62e',
   # 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.
@@ -187,7 +187,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': '3d1386f3ea3f0ce933e6e3def9a67b39e80f1ce6',
+  'angle_revision': '2319607679d7781ff9bab5e821a34574ecb0bcc3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -246,7 +246,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '237b8541c13f344050a5db3b93e6c43b5b5458be',
+  'devtools_frontend_revision': 'f9f8e4b0d42d1f45a4d6bf95fd28ccbf4cc3e271',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -302,7 +302,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': '7119a0278da3ae1044a0dcaaf979a2b5294a10ee',
+  'dawn_revision': '61e170b3c5f67da84bb28aca17abe78208732c36',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -881,7 +881,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'c440b23d505b810a49f3ee9ae55693f30b78c30e',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e521cd14da4a02274de5099543f0b30350e41be3',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1465,7 +1465,7 @@
   },
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '5185df5cad73ff76844db122d9c86900e66b7a2b',
+    Var('webrtc_git') + '/src.git' + '@' + '8d8bae65e67deed612bc6ec397d6f74481b6a59c',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1540,7 +1540,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6e3984a4c68ea883e183a3e8118f14b6a315ef2f',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8b2eec58cc7e7f938121f5d4e30051f01ac27117',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 3b34128..4835af69 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -267,6 +267,28 @@
 }
 #endif  // BUILDFLAG(ENABLE_MOJO_CDM)
 
+// Helper method that checks the RenderProcessHost is still alive before hopping
+// over to the IO thread.
+void MaybeCreateSafeBrowsing(
+    int rph_id,
+    content::ResourceContext* resource_context,
+    base::RepeatingCallback<scoped_refptr<safe_browsing::UrlCheckerDelegate>()>
+        get_checker_delegate,
+    mojo::PendingReceiver<safe_browsing::mojom::SafeBrowsing> receiver) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  content::RenderProcessHost* render_process_host =
+      content::RenderProcessHost::FromID(rph_id);
+  if (!render_process_host)
+    return;
+
+  base::PostTask(
+      FROM_HERE, {BrowserThread::IO},
+      base::BindOnce(&safe_browsing::MojoSafeBrowsingImpl::MaybeCreate, rph_id,
+                     resource_context, std::move(get_checker_delegate),
+                     std::move(receiver)));
+}
+
 }  // anonymous namespace
 
 std::string GetProduct() {
@@ -710,12 +732,12 @@
       render_process_host->GetBrowserContext()->GetResourceContext();
   registry->AddInterface(
       base::BindRepeating(
-          &safe_browsing::MojoSafeBrowsingImpl::MaybeCreate,
-          render_process_host->GetID(), resource_context,
+          &MaybeCreateSafeBrowsing, render_process_host->GetID(),
+          resource_context,
           base::BindRepeating(
               &AwContentBrowserClient::GetSafeBrowsingUrlCheckerDelegate,
               base::Unretained(this))),
-      base::CreateSingleThreadTaskRunner({BrowserThread::IO}));
+      base::CreateSingleThreadTaskRunner({BrowserThread::UI}));
 
 #if BUILDFLAG(ENABLE_SPELLCHECK)
   auto create_spellcheck_host =
diff --git a/android_webview/nonembedded/BUILD.gn b/android_webview/nonembedded/BUILD.gn
index 647bb88..5deebb9 100644
--- a/android_webview/nonembedded/BUILD.gn
+++ b/android_webview/nonembedded/BUILD.gn
@@ -133,7 +133,7 @@
     "java/res_devui/layout/two_line_list_item.xml",
     "java/res_devui/layout/two_line_sublist_item.xml",
     "java/res_devui/menu/crashes_options_menu.xml",
-    "java/res_devui/menu/navigation_menu.xml",
+    "java/res_devui/menu/options_menu.xml",
     "java/res_devui/values-night/colors.xml",
     "java/res_devui/values-night/styles.xml",
     "java/res_devui/values/colors.xml",
diff --git a/android_webview/nonembedded/java/res_devui/menu/navigation_menu.xml b/android_webview/nonembedded/java/res_devui/menu/options_menu.xml
similarity index 65%
rename from android_webview/nonembedded/java/res_devui/menu/navigation_menu.xml
rename to android_webview/nonembedded/java/res_devui/menu/options_menu.xml
index 167850bd..0999ad6 100644
--- a/android_webview/nonembedded/java/res_devui/menu/navigation_menu.xml
+++ b/android_webview/nonembedded/java/res_devui/menu/options_menu.xml
@@ -9,8 +9,13 @@
     <group android:id="@+id/nav_menu_group">
         <!--suppress HardcodedText -->
         <item
-             android:id="@+id/nav_menu_switch_provider"
+             android:id="@+id/options_menu_switch_provider"
              android:title="Change WebView Provider"
              android:showAsAction="never"/>
+        <!--suppress HardcodedText -->
+        <item
+             android:id="@+id/options_menu_report_bug"
+             android:title="Report WebView Bug"
+             android:showAsAction="never"/>
     </group>
 </menu>
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/MainActivity.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/MainActivity.java
index c517872..ec9d08b 100644
--- a/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/MainActivity.java
+++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/MainActivity.java
@@ -7,6 +7,7 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.provider.Settings;
@@ -156,17 +157,27 @@
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-            getMenuInflater().inflate(R.menu.navigation_menu, menu);
+            getMenuInflater().inflate(R.menu.options_menu, menu);
         }
         return true;
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        if (item.getItemId() == R.id.nav_menu_switch_provider
+        if (item.getItemId() == R.id.options_menu_switch_provider
                 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             startActivity(new Intent(Settings.ACTION_WEBVIEW_SETTINGS));
             return true;
+        } else if (item.getItemId() == R.id.options_menu_report_bug) {
+            Uri reportUri = new Uri.Builder()
+                                    .scheme("https")
+                                    .authority("bugs.chromium.org")
+                                    .path("/p/chromium/issues/entry")
+                                    .appendQueryParameter("template", "Webview+Bugs")
+                                    .appendQueryParameter("labels", "Via-WebView-DevTools")
+                                    .build();
+            startActivity(new Intent(Intent.ACTION_VIEW, reportUri));
+            return true;
         }
         return super.onOptionsItemSelected(item);
     }
diff --git a/ash/display/cros_display_config.cc b/ash/display/cros_display_config.cc
index 9e5bb2b..698b88b 100644
--- a/ash/display/cros_display_config.cc
+++ b/ash/display/cros_display_config.cc
@@ -4,16 +4,17 @@
 
 #include "ash/display/cros_display_config.h"
 
-#include <memory>
 #include <utility>
 
 #include "ash/display/display_configuration_controller.h"
+#include "ash/display/display_highlight_controller.h"
 #include "ash/display/display_prefs.h"
 #include "ash/display/overscan_calibrator.h"
 #include "ash/display/resolution_notification_controller.h"
 #include "ash/display/screen_orientation_controller.h"
 #include "ash/display/touch_calibrator_controller.h"
 #include "ash/display/window_tree_host_manager.h"
+#include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/tablet_mode_observer.h"
 #include "ash/public/mojom/cros_display_config.mojom.h"
 #include "ash/shell.h"
@@ -999,4 +1000,10 @@
   return iter == overscan_calibrators_.end() ? nullptr : iter->second.get();
 }
 
+void CrosDisplayConfig::HighlightDisplay(int64_t id) {
+  DCHECK(base::FeatureList::IsEnabled(features::kDisplayIdentification));
+
+  Shell::Get()->display_highlight_controller()->SetHighlightedDisplay(id);
+}
+
 }  // namespace ash
diff --git a/ash/display/cros_display_config.h b/ash/display/cros_display_config.h
index bf499d6..f76959f 100644
--- a/ash/display/cros_display_config.h
+++ b/ash/display/cros_display_config.h
@@ -53,6 +53,7 @@
                         mojom::DisplayConfigOperation op,
                         mojom::TouchCalibrationPtr calibration,
                         TouchCalibrationCallback callback) override;
+  void HighlightDisplay(int64_t id) override;
 
   TouchCalibratorController* touch_calibrator_for_test() {
     return touch_calibrator_.get();
diff --git a/ash/display/cros_display_config_unittest.cc b/ash/display/cros_display_config_unittest.cc
index 73d7b1a..bbdd1c92 100644
--- a/ash/display/cros_display_config_unittest.cc
+++ b/ash/display/cros_display_config_unittest.cc
@@ -4,8 +4,10 @@
 
 #include "ash/display/cros_display_config.h"
 
+#include "ash/display/display_highlight_controller.h"
 #include "ash/display/screen_orientation_controller.h"
 #include "ash/display/touch_calibrator_controller.h"
+#include "ash/public/cpp/ash_features.h"
 #include "ash/public/mojom/cros_display_config.mojom.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
@@ -71,12 +73,16 @@
   DISALLOW_COPY_AND_ASSIGN(TestObserver);
 };
 
+}  // namespace
+
 class CrosDisplayConfigTest : public AshTestBase {
  public:
   CrosDisplayConfigTest() {}
   ~CrosDisplayConfigTest() override {}
 
   void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(features::kDisplayIdentification);
+
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
         switches::kUseFirstDisplayAsInternal);
     AshTestBase::SetUp();
@@ -193,16 +199,20 @@
     return touch_calibrator && touch_calibrator->IsCalibrating();
   }
 
+  void HighlightDisplay(int64_t id) {
+    cros_display_config_->HighlightDisplay(id);
+  }
+
   CrosDisplayConfig* cros_display_config() { return cros_display_config_; }
 
  private:
   CrosDisplayConfig* cros_display_config_ = nullptr;
 
+  base::test::ScopedFeatureList scoped_feature_list_;
+
   DISALLOW_COPY_AND_ASSIGN(CrosDisplayConfigTest);
 };
 
-}  // namespace
-
 TEST_F(CrosDisplayConfigTest, OnDisplayConfigChanged) {
   TestObserver observer;
   mojo::AssociatedRemote<mojom::CrosDisplayConfigObserver> observer_remote;
@@ -808,4 +818,28 @@
   EXPECT_EQ(display::Display::ROTATE_0, display.rotation());
 }
 
+TEST_F(CrosDisplayConfigTest, HighlightDisplayValid) {
+  UpdateDisplay("500x400,500x400");
+
+  const display::Display& display = display_manager()->GetDisplayAt(0);
+  const int64_t display_id = display.id();
+
+  HighlightDisplay(display_id);
+
+  views::Widget* widget =
+      Shell::Get()->display_highlight_controller()->GetWidgetForTesting();
+  ASSERT_NE(widget, nullptr);
+  EXPECT_EQ(widget->GetNativeWindow()->GetRootWindow(),
+            Shell::GetRootWindowForDisplayId(display_id));
+}
+
+TEST_F(CrosDisplayConfigTest, HighlightDisplayInvalid) {
+  UpdateDisplay("500x400,500x400");
+
+  HighlightDisplay(display::kInvalidDisplayId);
+
+  EXPECT_EQ(Shell::Get()->display_highlight_controller()->GetWidgetForTesting(),
+            nullptr);
+}
+
 }  // namespace ash
diff --git a/ash/public/cpp/app_list/app_list_features.cc b/ash/public/cpp/app_list/app_list_features.cc
index 11f16f10..66802f07 100644
--- a/ash/public/cpp/app_list/app_list_features.cc
+++ b/ash/public/cpp/app_list/app_list_features.cc
@@ -50,6 +50,8 @@
                                               base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kEnableAggregatedMlAppRanking{
     "EnableAggregatedMlAppRanking", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kLauncherSettingsSearch{"LauncherSettingsSearch",
+                                            base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kScalableAppList{"ScalableAppList",
                                      base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kEnableFuzzyAppSearch{"EnableFuzzyAppSearch",
@@ -127,6 +129,10 @@
   return base::FeatureList::IsEnabled(kEnableAggregatedMlAppRanking);
 }
 
+bool IsLauncherSettingsSearchEnabled() {
+  return base::FeatureList::IsEnabled(kLauncherSettingsSearch);
+}
+
 bool IsScalableAppListEnabled() {
   return base::FeatureList::IsEnabled(kScalableAppList);
 }
diff --git a/ash/public/cpp/app_list/app_list_features.h b/ash/public/cpp/app_list/app_list_features.h
index dd7a5ce..387472a 100644
--- a/ash/public/cpp/app_list/app_list_features.h
+++ b/ash/public/cpp/app_list/app_list_features.h
@@ -78,6 +78,9 @@
 // Enables using exact string search for non latin locales.
 ASH_PUBLIC_EXPORT extern const base::Feature kEnableExactMatchForNonLatinLocale;
 
+// Enables launcher search results for OS settings.
+ASH_PUBLIC_EXPORT extern const base::Feature kLauncherSettingsSearch;
+
 // If enabled, app list will support separate configurations (for app list items
 // sizing and spacing) for smaller screens (instead of a single configuration
 // that optionally gets scaled down).
@@ -107,6 +110,7 @@
 bool ASH_PUBLIC_EXPORT IsScalableAppListEnabled();
 bool ASH_PUBLIC_EXPORT IsFuzzyAppSearchEnabled();
 bool ASH_PUBLIC_EXPORT IsExactMatchForNonLatinLocaleEnabled();
+bool ASH_PUBLIC_EXPORT IsLauncherSettingsSearchEnabled();
 bool ASH_PUBLIC_EXPORT IsAggregatedMlSearchRankingEnabled();
 
 std::string ASH_PUBLIC_EXPORT AnswerServerUrl();
diff --git a/ash/public/cpp/default_scale_factor_retriever_unittest.cc b/ash/public/cpp/default_scale_factor_retriever_unittest.cc
index 1e075c90..1970aa0d 100644
--- a/ash/public/cpp/default_scale_factor_retriever_unittest.cc
+++ b/ash/public/cpp/default_scale_factor_retriever_unittest.cc
@@ -62,6 +62,7 @@
                         ash::mojom::DisplayConfigOperation op,
                         ash::mojom::TouchCalibrationPtr calibration,
                         TouchCalibrationCallback callback) override {}
+  void HighlightDisplay(int64_t id) override {}
 
  private:
   mojo::Receiver<ash::mojom::CrosDisplayConfigController> receiver_{this};
diff --git a/ash/public/mojom/cros_display_config.mojom b/ash/public/mojom/cros_display_config.mojom
index 41c57a0..b3096ad6 100644
--- a/ash/public/mojom/cros_display_config.mojom
+++ b/ash/public/mojom/cros_display_config.mojom
@@ -298,6 +298,10 @@
                    DisplayConfigOperation op,
                    TouchCalibration? calibration) =>
     (DisplayConfigResult result);
+
+  // Sets |id| of display to render identification highlight on. Invalid |id|
+  // turns identification highlight off.
+  HighlightDisplay(int64 id);
 };
 
 // Interface for clients needing to be informed when the display configuration
diff --git a/ash/shelf/drag_handle.cc b/ash/shelf/drag_handle.cc
index dfea206a..a9ef825f 100644
--- a/ash/shelf/drag_handle.cc
+++ b/ash/shelf/drag_handle.cc
@@ -80,7 +80,8 @@
 
 }  // namespace
 
-DragHandle::DragHandle(int drag_handle_corner_radius) {
+DragHandle::DragHandle(int drag_handle_corner_radius, Shelf* shelf)
+    : shelf_(shelf) {
   SetPaintToLayer(ui::LAYER_SOLID_COLOR);
   layer()->SetRoundedCornerRadius(
       {drag_handle_corner_radius, drag_handle_corner_radius,
@@ -116,8 +117,7 @@
     return false;
   }
   show_nudge_animation_in_progress_ = true;
-  auto_hide_lock_ = std::make_unique<Shelf::ScopedAutoHideLock>(
-      ash::Shelf::ForWindow(GetWidget()->GetNativeWindow()));
+  auto_hide_lock_ = std::make_unique<Shelf::ScopedAutoHideLock>(shelf_);
 
   StopDragHandleNudgeShowTimer();
   ShowDragHandleNudge();
diff --git a/ash/shelf/drag_handle.h b/ash/shelf/drag_handle.h
index b8a436c..f3c53bf 100644
--- a/ash/shelf/drag_handle.h
+++ b/ash/shelf/drag_handle.h
@@ -28,7 +28,7 @@
                               public ShellObserver,
                               public ui::ImplicitAnimationObserver {
  public:
-  explicit DragHandle(int drag_handle_corner_radius);
+  DragHandle(int drag_handle_corner_radius, Shelf* shelf);
   DragHandle(const DragHandle&) = delete;
   ~DragHandle() override;
 
@@ -128,6 +128,9 @@
   // Stops the timer to show the drag handle nudge.
   void StopDragHandleNudgeShowTimer();
 
+  // Pointer to the shelf that owns the drag handle.
+  Shelf* const shelf_;
+
   // Timer to hide drag handle nudge if it has a timed life.
   base::OneShotTimer hide_drag_handle_nudge_timer_;
 
diff --git a/ash/shelf/shelf_drag_handle_unittest.cc b/ash/shelf/shelf_drag_handle_unittest.cc
index d86d85ad..0d96c0a 100644
--- a/ash/shelf/shelf_drag_handle_unittest.cc
+++ b/ash/shelf/shelf_drag_handle_unittest.cc
@@ -100,6 +100,27 @@
       GetShelfWidget()->GetDragHandle()->gesture_nudge_target_visibility());
 }
 
+// Tests that the drag handle nudge nudge is hidden when closing the widget and
+// setting the ShelfBackgroundType to kHomeLauncher.
+TEST_F(DragHandleContextualNudgeTest, DragHandleNudgeHiddenOnClose) {
+  // Creates a widget to put shelf into in-app state.
+  views::Widget* widget = CreateTestWidget();
+  widget->Maximize();
+  TabletModeControllerTestApi().EnterTabletMode();
+  EXPECT_EQ(ShelfBackgroundType::kInApp, GetShelfWidget()->GetBackgroundType());
+
+  DragHandle* const drag_handle = GetShelfWidget()->GetDragHandle();
+
+  ASSERT_TRUE(drag_handle->has_show_drag_handle_timer_for_testing());
+  drag_handle->fire_show_drag_handle_timer_for_testing();
+  EXPECT_TRUE(drag_handle->gesture_nudge_target_visibility());
+
+  // Close the widget.
+  widget->CloseWithReason(views::Widget::ClosedReason::kCloseButtonClicked);
+  EXPECT_FALSE(drag_handle->GetVisible());
+  EXPECT_FALSE(drag_handle->gesture_nudge_target_visibility());
+}
+
 // Checks that the shelf cannot be auto hidden while animating shelf drag handle
 // nudge.
 TEST_F(DragHandleContextualNudgeTest,
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index ea4db25..fae6427 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -1157,6 +1157,7 @@
   SetState(state_.visibility_state);
   LayoutShelf(/*animate=*/true);
   MaybeUpdateShelfBackground(AnimationChangeType::IMMEDIATE);
+  UpdateContextualNudges();
 }
 
 void ShelfLayoutManager::OnTabletModeStarted() {
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index 08142e66..859cf74 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -107,7 +107,7 @@
                                   public ShelfBackgroundAnimatorObserver,
                                   public HotseatTransitionAnimator::Observer {
  public:
-  explicit DelegateView(ShelfWidget* shelf);
+  DelegateView(ShelfWidget* shelf_widget, Shelf* shelf);
   ~DelegateView() override;
 
   void set_focus_cycler(FocusCycler* focus_cycler) {
@@ -211,7 +211,7 @@
   DISALLOW_COPY_AND_ASSIGN(DelegateView);
 };
 
-ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf_widget)
+ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf_widget, Shelf* shelf)
     : shelf_widget_(shelf_widget),
       focus_cycler_(nullptr),
       opaque_background_(std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR)),
@@ -234,8 +234,8 @@
       AshColorProvider::Get()->GetRippleAttributes(
           ShelfConfig::Get()->GetDefaultShelfColor());
 
-  drag_handle_ =
-      AddChildView(std::make_unique<DragHandle>(kDragHandleCornerRadius));
+  drag_handle_ = AddChildView(
+      std::make_unique<DragHandle>(kDragHandleCornerRadius, shelf));
 
   animating_drag_handle_.SetColor(ripple_attributes.base_color);
   animating_drag_handle_.SetOpacity(ripple_attributes.inkdrop_opacity + 0.075);
@@ -582,7 +582,7 @@
     : shelf_(shelf),
       background_animator_(shelf_, Shell::Get()->wallpaper_controller()),
       shelf_layout_manager_(new ShelfLayoutManager(this, shelf)),
-      delegate_view_(new DelegateView(this)),
+      delegate_view_(new DelegateView(this, shelf_)),
       scoped_session_observer_(this) {
   DCHECK(shelf_);
 }
diff --git a/ash/strings/ash_strings_bn.xtb b/ash/strings/ash_strings_bn.xtb
index 33387a16..3f982a3 100644
--- a/ash/strings/ash_strings_bn.xtb
+++ b/ash/strings/ash_strings_bn.xtb
@@ -104,6 +104,7 @@
 <translation id="2268813581635650749">সবগুলি থেকে সাইন-আউট করুন</translation>
 <translation id="2277103315734023688">এগিয়ে যান</translation>
 <translation id="2292698582925480719">স্কেল প্রদর্শন করুন</translation>
+<translation id="2295777434187870477">মাইক্রোফোন চালু করা আছে, টগল করলে এটি মিউট হয়ে যাবে।</translation>
 <translation id="2298170939937364391">ফুল-স্ক্রিন ম্যাগনিফায়ার চালু করা আছে। আবার Ctrl+Search+M প্রেস করে সেটিকে বন্ধ করুন।</translation>
 <translation id="2302092602801625023">এই অ্যাকাউন্টটি Family Link দ্বারা ম্যানেজ করা</translation>
 <translation id="2303600792989757991">উইন্ডোর ওভারভিউ টগল করুন</translation>
@@ -137,6 +138,7 @@
 <translation id="2658778018866295321">ক্লিক করে ড্র্যাগ করুন</translation>
 <translation id="2700493154570097719">আপনার কীবোর্ড সেট করুন</translation>
 <translation id="2704781753052663061">অন্য ওয়াই-ফাই নেটওয়ার্কে যোগ দিন</translation>
+<translation id="2705001408393684014">মাইক্রোফোন টগল করুন। <ph name="STATE_TEXT" /></translation>
 <translation id="2718395828230677721">নাইট লাইট</translation>
 <translation id="2727977024730340865">একটি নিম্ন শক্তির চার্জার প্লাগইন করা হয়েছে৷ বিশ্বস্ত ব্যাটারি চার্জ নাও হতে পারে৷</translation>
 <translation id="2792498699870441125">Alt+Search</translation>
@@ -295,6 +297,7 @@
 <translation id="4665114317261903604">'বিরক্ত করবে না' মোড টগল করুন। <ph name="STATE_TEXT" /></translation>
 <translation id="4696813013609194136">অভিভাবকীয় কোড দিয়ে ডিভাইস আনলক করুন</translation>
 <translation id="4702647871202761252">গোপনীয়তা স্ক্রিন বন্ধ করা আছে</translation>
+<translation id="4705716602320768426">ফাইলের ব্যাপারে নিজের মতামত জানান</translation>
 <translation id="4710243778082831592">IME সেটিংস</translation>
 <translation id="4731797938093519117">অভিভাবকীয় অ্যাক্সেস</translation>
 <translation id="4734965478015604180">অনুভূমিক</translation>
@@ -375,6 +378,7 @@
 <translation id="5901316534475909376">Shift+Esc</translation>
 <translation id="5911909173233110115"><ph name="USERNAME" /> (<ph name="MAIL" />)</translation>
 <translation id="5916664084637901428">চালু</translation>
+<translation id="5920710855273935292">মাইক্রোফোন মিউট করা আছে।</translation>
 <translation id="5947494881799873997">ফেরান</translation>
 <translation id="595202126637698455">কার্য-সম্পাদনা ট্রেস করা সক্ষম রয়েছে</translation>
 <translation id="5957083217255311415">মোবাইল ডেটা বন্ধ করা আছে।</translation>
diff --git a/ash/system/message_center/unified_message_center_bubble.cc b/ash/system/message_center/unified_message_center_bubble.cc
index 8cc5a2cd..c2bf44bc 100644
--- a/ash/system/message_center/unified_message_center_bubble.cc
+++ b/ash/system/message_center/unified_message_center_bubble.cc
@@ -85,18 +85,6 @@
       bubble_view_->AddChildView(std::make_unique<UnifiedMessageCenterView>(
           nullptr /* parent */, tray->model(), this));
 
-  // Check if the message center bubble should be collapsed or expanded
-  // when it is initially opened.
-  if (CalculateAvailableHeight() < kMessageCenterCollapseThreshold &&
-      message_center_view_->GetPreferredSize().height()) {
-    if (tray_->IsQuickSettingsExplicitlyExpanded()) {
-      message_center_view_->SetCollapsed(false /*animate*/);
-    } else {
-      message_center_view_->SetExpanded();
-      tray_->EnsureQuickSettingsCollapsed(false /*animate*/);
-    }
-  }
-
   message_center_view_->AddObserver(this);
 }
 
@@ -116,6 +104,18 @@
 
   bubble_view_->InitializeAndShowBubble();
 
+  // Check if the message center bubble should be collapsed or expanded
+  // when it is initially opened.
+  if (CalculateAvailableHeight() < kMessageCenterCollapseThreshold &&
+      message_center_view_->GetPreferredSize().height()) {
+    if (tray_->IsQuickSettingsExplicitlyExpanded()) {
+      message_center_view_->SetCollapsed(false /*animate*/);
+    } else {
+      message_center_view_->SetExpanded();
+      tray_->EnsureQuickSettingsCollapsed(false /*animate*/);
+    }
+  }
+
   UpdatePosition();
 }
 
diff --git a/base/fuchsia/test_component_context_for_process.cc b/base/fuchsia/test_component_context_for_process.cc
index 3f2f9ea..22a30499 100644
--- a/base/fuchsia/test_component_context_for_process.cc
+++ b/base/fuchsia/test_component_context_for_process.cc
@@ -9,7 +9,6 @@
 #include <lib/fidl/cpp/interface_handle.h>
 #include <lib/sys/cpp/component_context.h>
 
-#include "base/files/file_enumerator.h"
 #include "base/fuchsia/default_context.h"
 #include "base/fuchsia/filtered_service_directory.h"
 #include "base/fuchsia/fuchsia_logging.h"
@@ -17,8 +16,7 @@
 
 namespace base {
 
-TestComponentContextForProcess::TestComponentContextForProcess(
-    InitialState initial_state) {
+TestComponentContextForProcess::TestComponentContextForProcess() {
   // TODO(https://crbug.com/1038786): Migrate to sys::ComponentContextProvider
   // once it provides access to an sys::OutgoingDirectory or PseudoDir through
   // which to publish additional_services().
@@ -28,15 +26,6 @@
   context_services_ = std::make_unique<fuchsia::FilteredServiceDirectory>(
       base::fuchsia::ComponentContextForCurrentProcess()->svc().get());
 
-  // Push all services from /svc to the test context if requested.
-  if (initial_state == InitialState::kCloneAll) {
-    base::FileEnumerator file_enum(base::FilePath("/svc"), false,
-                                   base::FileEnumerator::FILES);
-    for (auto file = file_enum.Next(); !file.empty(); file = file_enum.Next()) {
-      AddService(file.BaseName().value());
-    }
-  }
-
   // Create a ServiceDirectory backed by the contents of |incoming_directory|.
   fidl::InterfaceHandle<::fuchsia::io::Directory> incoming_directory;
   context_services_->ConnectClient(incoming_directory.NewRequest());
@@ -71,15 +60,10 @@
   return context_services_->outgoing_directory();
 }
 
-void TestComponentContextForProcess::AddService(
-    const base::StringPiece service) {
-  context_services_->AddService(service);
-}
-
 void TestComponentContextForProcess::AddServices(
     base::span<const base::StringPiece> services) {
   for (auto service : services)
-    AddService(service);
+    context_services_->AddService(service);
 }
 
 }  // namespace base
diff --git a/base/fuchsia/test_component_context_for_process.h b/base/fuchsia/test_component_context_for_process.h
index 0c35447..f2e2b42 100644
--- a/base/fuchsia/test_component_context_for_process.h
+++ b/base/fuchsia/test_component_context_for_process.h
@@ -41,25 +41,18 @@
 // test base-class:
 //
 //   TEST(MyFunkyTest, IsFunky) {
-//     TestComponentContextForProcess test_context;
+//     TestComponentContextForTest test_context;
 //     // Configure the |test_context|.
 //     // Run tests of code that uses ComponentContextForProcess().
 //   }
 //
-// By default created context doesn't expose any services. Services from the
-// original process-global ComponentContext (usually the environment in which
-// the test process is running), can be exposed through the |test_context| with
-// AddServices(), during test setup:
+// Services from the original process-global ComponentContext (usually the
+// environment in which the test process is running), can be exposed through the
+// |test_context| with AddServices(), during test setup:
 //
 //   test_context.AddServices({fuchsia::memorypressure::Provider::Name_, ...});
 //   // ... Execute tests which use fuchsia.memorypressure.Provider ...
 //
-// Alternatively InitialState::kEmpty can be passed to the constructor to expose
-// all services listed in /svc, e.g.:
-//
-//   TestComponentContextForProcess test_context(
-//       TestComponentContextForProcess::InitialState::kEmpty);
-//
 // Fake/mock implementations can be exposed via additional_services():
 //
 //   ScopedServiceBinding<funky::Service> binding(
@@ -75,13 +68,7 @@
 //
 class BASE_EXPORT TestComponentContextForProcess {
  public:
-  enum class InitialState {
-    kEmpty,
-    kCloneAll,
-  };
-
-  TestComponentContextForProcess(
-      InitialState initial_state = InitialState::kEmpty);
+  TestComponentContextForProcess();
   ~TestComponentContextForProcess();
 
   TestComponentContextForProcess(const TestComponentContextForProcess&) =
@@ -93,9 +80,8 @@
   // published for use by the code-under test.
   sys::OutgoingDirectory* additional_services();
 
-  // Allows the specified service(s) from the original ComponentContext to be
+  // Allows the specified services from the original ComponentContext to be
   // exposed via the test default ComponentContext.
-  void AddService(const base::StringPiece service);
   void AddServices(base::span<const base::StringPiece> services);
 
   // Returns the directory of services that the code under test has published
diff --git a/build/android/gyp/dex.py b/build/android/gyp/dex.py
index 82ddac0..8dfdeb3 100755
--- a/build/android/gyp/dex.py
+++ b/build/android/gyp/dex.py
@@ -24,7 +24,12 @@
 
 _IGNORE_WARNINGS = (
     # A play services library triggers this.
-    'Type `libcore.io.Memory` was not found', )
+    r'Type `libcore.io.Memory` was not found',
+    # Filter out warnings caused by our fake main dex list used to enable
+    # multidex on library targets.
+    # Warning: Application does not contain `Foo` as referenced in main-dex-list
+    r'does not contain `Foo`',
+)
 
 
 def _ParseArgs(args):
@@ -114,11 +119,6 @@
   if options.main_dex_list_path and not options.multi_dex:
     parser.error('--main-dex-list-path is unused if multidex is not enabled')
 
-  if options.desugar and options.classpath is None:
-    parser.error('--classpath required with use of --desugar')
-  if options.desugar and options.bootclasspath is None:
-    parser.error('--bootclasspath required with use of --desugar')
-
   options.class_inputs = build_utils.ParseGnList(options.class_inputs)
   options.class_inputs_filearg = build_utils.ParseGnList(
       options.class_inputs_filearg)
@@ -135,12 +135,18 @@
   dex_cmd = dex_cmd + ['--output', output_path] + input_paths
 
   def stderr_filter(output):
-    # Filter out warnings caused by our fake main dex list used to enable
-    # multidex on library targets.
-    # Warning: Application does not contain `Foo` as referenced in main-dex-list
-    pattern = r'does not contain `Foo`'
-    pattern += '|' + '|'.join(re.escape(p) for p in _IGNORE_WARNINGS)
-    output = build_utils.FilterLines(output, pattern)
+    patterns = _IGNORE_WARNINGS
+    # No classpath means we are using Bazel's Desugar tool to desugar lambdas
+    # and interface methods, in which case we intentionally do not pass a
+    # classpath to D8.
+    # Not having a classpath makes incremental dexing much more effective.
+    # D8 will still be used for backported method desugaring.
+    # We still use D8 for backported method desugaring.
+    if '--classpath' not in dex_cmd:
+      patterns = list(patterns) + ['default or static interface methods']
+
+    combined_pattern = '|'.join(re.escape(p) for p in patterns)
+    output = build_utils.FilterLines(output, combined_pattern)
 
     # Each warning has a prefix line of tthe file it's from. If we've filtered
     # out the warning, then also filter out the file header.
@@ -478,7 +484,10 @@
   if options.min_api:
     dex_cmd += ['--min-api', options.min_api]
 
-  if options.desugar:
+  if not options.desugar:
+    dex_cmd += ['--no-desugaring']
+  elif options.classpath:
+    # Don't pass classpath when Desugar.jar is doing interface desugaring.
     dex_cmd += ['--lib', build_utils.JAVA_HOME]
     for path in options.bootclasspath:
       dex_cmd += ['--lib', path]
@@ -488,8 +497,6 @@
     depfile_deps += options.bootclasspath
     input_paths += options.classpath
     input_paths += options.bootclasspath
-  else:
-    dex_cmd += ['--no-desugaring']
 
   if options.force_enable_assertions:
     dex_cmd += ['--force-enable-assertions']
diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py
index 3d58b9b..f2fae724 100755
--- a/build/android/gyp/proguard.py
+++ b/build/android/gyp/proguard.py
@@ -165,9 +165,6 @@
       '--force-enable-assertions',
       action='store_true',
       help='Forcefully enable javac generated assertion code.')
-  parser.add_argument(
-      '--desugar', action='store_true', help='Enable R8 Desugaring')
-
 
   options = parser.parse_args(args)
 
@@ -238,9 +235,6 @@
         tmp_mapping_path,
     ]
 
-    if not options.desugar:
-      cmd += ['--no-desugaring']
-
     for lib in libraries:
       cmd += ['--lib', lib]
 
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index f63f5f3..70404a04 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -234,8 +234,9 @@
     # For local development, it's nice to not fail builds on warnings.
     java_warnings_as_errors = !is_java_debug
 
-    # Desugar with D8 rather than Desugar tool.
-    desugar_with_d8 = is_java_debug
+    # Desugar lambdas and interfaces methods using Desugar.jar rather than
+    # D8/R8. D8/R8 will still be used for backported method desugaring.
+    enable_bazel_desugar = true
   }
 
   # Path to where selected build variables are written to.
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index cf80acb..b97590a 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -1084,10 +1084,6 @@
         args += [ "--force-enable-assertions" ]
       }
 
-      if (desugar_with_d8) {
-        args += [ "--desugar" ]
-      }
-
       if (defined(invoker.args)) {
         args += invoker.args
       }
@@ -1158,16 +1154,18 @@
     _enable_multidex =
         !defined(invoker.enable_multidex) || invoker.enable_multidex
     _enable_main_dex_list = _enable_multidex && _min_sdk_version < 21
+    _enable_desugar = !defined(invoker.enable_desugar) || invoker.enable_desugar
+    _desugar_needs_classpath = _enable_desugar && !enable_bazel_desugar
+
     if (!_enable_main_dex_list) {
       if (defined(invoker.negative_main_dex_globs)) {
         not_needed(invoker, [ "negative_main_dex_globs" ])
       }
     }
 
-    # When using d8 to desugar, the dex merge step must not be set to a higher
-    # minSdkVersion than the libraries in order for the proper backported
-    # methods to be included.
-    if (invoker.enable_desugar && defined(invoker.input_dex_filearg)) {
+    # For D8's backported method desugaring to work properly, the dex merge step
+    # must not be set to a higher minSdkVersion than it was for the libraries.
+    if (_enable_desugar && defined(invoker.input_dex_filearg)) {
       _min_sdk_version = default_min_sdk_version
     }
 
@@ -1183,7 +1181,7 @@
       _main_dex_rules = "//build/android/main_dex_classes.flags"
     }
 
-    if (invoker.enable_desugar || _proguard_enabled) {
+    if (_desugar_needs_classpath || _proguard_enabled) {
       _rebased_build_config = rebase_path(invoker.build_config, root_build_dir)
     }
 
@@ -1445,9 +1443,11 @@
           args += [ "--release" ]
         }
 
-        if (invoker.enable_desugar) {
+        if (_enable_desugar) {
+          args += [ "--desugar" ]
+        }
+        if (_desugar_needs_classpath) {
           args += [
-            "--desugar",
             "--bootclasspath=@FileArg($_rebased_build_config:android:sdk_jars)",
             "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)",
           ]
@@ -3630,7 +3630,7 @@
                                    "jar_included_patterns",
                                    "skip_jetify",
                                  ])
-          enable_desugar = _enable_desugar && !desugar_with_d8
+          enable_desugar = _enable_desugar && enable_bazel_desugar
           is_prebuilt = _is_prebuilt
           enable_build_hooks_android = _enable_build_hooks_android
           build_config = _build_config
@@ -3666,7 +3666,7 @@
           dex("${target_name}__dex") {
             input_class_jars = [ _final_jar_path ]
 
-            enable_desugar = _enable_desugar && desugar_with_d8
+            enable_desugar = _enable_desugar
 
             # There's no value in per-class dexing prebuilts since they never
             # change just one class at a time.
@@ -3674,7 +3674,7 @@
             output = _dex_path
             deps = [ ":$_process_prebuilt_target_name" ]
 
-            if (enable_desugar) {
+            if (enable_desugar && !enable_bazel_desugar) {
               build_config = _build_config
               final_ijar_path = _final_ijar_path
               deps += _java_header_deps + [ ":$_header_target_name" ]
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index d27fdfb..1640a1d 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -1674,7 +1674,6 @@
       deps = _deps
       build_config = _build_config
       proguard_enabled = true
-      enable_desugar = desugar_with_d8
       forward_variables_from(invoker,
                              [
                                "proguard_configs",
@@ -2921,7 +2920,6 @@
                                  "disable_r8_outlining",
                                  "dexlayout_profile",
                                ])
-        enable_desugar = desugar_with_d8
         min_sdk_version = _min_sdk_version
         proguard_enabled = _proguard_enabled
         build_config = _build_config
@@ -4636,7 +4634,6 @@
                                    "min_sdk_version",
                                  ])
           enable_multidex = _enable_multidex
-          enable_desugar = desugar_with_d8
           proguard_enabled = true
           proguard_mapping_path = _proguard_mapping_path
           proguard_sourcefile_suffix = "$android_channel-$_version_code"
diff --git a/build/config/ios/ios_test_runner_config.gni b/build/config/ios/ios_test_runner_config.gni
deleted file mode 100644
index f28533b..0000000
--- a/build/config/ios/ios_test_runner_config.gni
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-declare_args() {
-  # Controls what version of xcode to use for iOS testers. Note that this
-  # version should be in alignment with the swarming named caches used by tests,
-  # defined under src/testing/buildbot/ to avoid performance issues.
-  test_runner_xcode_build_version = "11c29"
-}
diff --git a/build/config/ios/ios_test_runner_wrapper.gni b/build/config/ios/ios_test_runner_wrapper.gni
index a70074f..67c5bf9 100644
--- a/build/config/ios/ios_test_runner_wrapper.gni
+++ b/build/config/ios/ios_test_runner_wrapper.gni
@@ -4,7 +4,6 @@
 
 import("//build/config/coverage/coverage.gni")
 import("//build/config/ios/ios_sdk.gni")
-import("//build/config/ios/ios_test_runner_config.gni")
 import("//build/util/generate_wrapper.gni")
 
 # Invokes generate_wrapper to create an executable script wrapping iOS'
@@ -71,11 +70,6 @@
       "@WrappedPath(${_rebased_mac_toolchain})",
     ]
 
-    executable_args += [
-      "--xcode-build-version",
-      test_runner_xcode_build_version,
-    ]
-
     # Default retries to 3
     if (!defined(retries)) {
       retries = 3
diff --git a/chrome/VERSION b/chrome/VERSION
index bc357c0..cf8de11b 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=84
 MINOR=0
-BUILD=4109
+BUILD=4110
 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 9025cc9..43ce7bc 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -1538,6 +1538,7 @@
   "java/src/org/chromium/chrome/browser/suggestions/ThumbnailGradient.java",
   "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSites.java",
   "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesBridge.java",
+  "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelper.java",
   "java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtils.java",
   "java/src/org/chromium/chrome/browser/suggestions/tile/SiteSection.java",
   "java/src/org/chromium/chrome/browser/suggestions/tile/SiteSectionViewHolder.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index a20cf34..8a0c2681 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -465,6 +465,7 @@
   "javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java",
   "javatests/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsTest.java",
   "javatests/src/org/chromium/chrome/browser/suggestions/NavigationRecorderTest.java",
+  "javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelperTest.java",
   "javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtilsTest.java",
   "javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java",
   "javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupTest.java",
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java
index 99a250c..2c41636 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java
@@ -138,6 +138,9 @@
         void reportManageInterests(long nativeFeedStreamSurface, FeedStreamSurface caller);
         // TODO(jianli): Call this function at the appropriate time.
         void reportContextMenuOpened(long nativeFeedStreamSurface, FeedStreamSurface caller);
+        // TODO(jianli): Call this function at the appropriate time.
+        void reportStreamScrolled(
+                long nativeFeedStreamSurface, FeedStreamSurface caller, int distanceDp);
         void loadMore(long nativeFeedStreamSurface, FeedStreamSurface caller);
         void processThereAndBackAgain(
                 long nativeFeedStreamSurface, FeedStreamSurface caller, byte[] data);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LauncherShortcutActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/LauncherShortcutActivity.java
index bcf8014..e5f4356 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/LauncherShortcutActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LauncherShortcutActivity.java
@@ -36,6 +36,8 @@
     @VisibleForTesting
     static final String DYNAMIC_OPEN_NEW_INCOGNITO_TAB_ID = "dynamic-new-incognito-tab-shortcut";
 
+    private static String sLabelForTesting;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -75,7 +77,10 @@
         boolean incognitoShortcutAdded =
                 preferences.readBoolean(ChromePreferenceKeys.INCOGNITO_SHORTCUT_ADDED, false);
 
-        if (incognitoEnabled && !incognitoShortcutAdded) {
+        // Add the shortcut regardless of whether it was previously added in case the locale has
+        // changed since the last addition.
+        // TODO(https://crbug.com/1068847): Investigate better locale change handling.
+        if (incognitoEnabled) {
             boolean success = LauncherShortcutActivity.addIncognitoLauncherShortcut(context);
 
             // Save a shared preference indicating the incognito shortcut has been added.
@@ -104,8 +109,10 @@
                 new ShortcutInfo.Builder(context, DYNAMIC_OPEN_NEW_INCOGNITO_TAB_ID)
                         .setShortLabel(context.getResources().getString(
                                 R.string.accessibility_tabstrip_incognito_identifier))
-                        .setLongLabel(
-                                context.getResources().getString(R.string.menu_new_incognito_tab))
+                        .setLongLabel(sLabelForTesting != null
+                                        ? sLabelForTesting
+                                        : context.getResources().getString(
+                                                R.string.menu_new_incognito_tab))
                         .setIcon(Icon.createWithResource(context, R.drawable.shortcut_incognito))
                         .setIntent(intent)
                         .build();
@@ -142,4 +149,9 @@
 
         return newIntent;
     }
+
+    @VisibleForTesting
+    public static void setDynamicShortcutStringForTesting(String label) {
+        sLabelForTesting = label;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsView.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsView.java
index 8e8cb23e..0e70a985 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DistilledPagePrefsView.java
@@ -70,8 +70,12 @@
      */
     public DistilledPagePrefsView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mDistilledPagePrefs = DomDistillerServiceFactory.getForProfile(
-                Profile.getLastUsedProfile()).getDistilledPagePrefs();
+        // TODO (https://crbug.com/1048632): Use the current profile (i.e., regular profile or
+        // incognito profile) instead of always using regular profile. It works correctly now, but
+        // it is not safe.
+        mDistilledPagePrefs =
+                DomDistillerServiceFactory.getForProfile(Profile.getLastUsedRegularProfile())
+                        .getDistilledPagePrefs();
         mColorModeButtons = new HashMap<Integer /* Theme */, RadioButton>();
         mPercentageFormatter = NumberFormat.getPercentInstance(Locale.getDefault());
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java
index 34b7d8a1..5e1f855 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java
@@ -182,29 +182,6 @@
     }
 
     /**
-     * Records how content suggestions have been updated in the UI.
-     * @param result result key, one of {@link ContentSuggestionsUIUpdateResult}'s values.
-     */
-    public static void recordUIUpdateResult(
-            @ContentSuggestionsUIUpdateResult int result) {
-        RecordHistogram.recordEnumeratedHistogram("NewTabPage.ContentSuggestions.UIUpdateResult2",
-                result, ContentSuggestionsUIUpdateResult.NUM_ENTRIES);
-    }
-
-    /**
-     * Record how many content suggestions have been seen by the user in the UI section before the
-     * section was successfully updated.
-     * @param numberOfSuggestionsSeen The number of content suggestions seen so far in the section.
-     */
-    public static void recordNumberOfSuggestionsSeenBeforeUIUpdateSuccess(
-            int numberOfSuggestionsSeen) {
-        assert numberOfSuggestionsSeen >= 0;
-        RecordHistogram.recordCount100Histogram(
-                "NewTabPage.ContentSuggestions.UIUpdateSuccessNumberOfSuggestionsSeen",
-                numberOfSuggestionsSeen);
-    }
-
-    /**
      * Record a NTP impression (even potential ones to make informed product decisions). If the
      * impression type is {@link NewTabPageUma#NTP_IMPRESSION_REGULAR}, also records a user action.
      * @param impressionType Type of the impression from NewTabPageUma.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
index 55a7459..2721530 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
@@ -11,7 +11,6 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.Log;
-import org.chromium.chrome.browser.ntp.NewTabPageUma;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder.PartialBindCallback;
 import org.chromium.chrome.browser.ntp.snippets.CategoryInt;
 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus;
@@ -385,16 +384,7 @@
         mOfflineModelObserver.updateAllSuggestionsOfflineAvailability(
                 reportPrefetchedSuggestionsCount);
 
-        if (!keepSectionSize) {
-            NewTabPageUma.recordUIUpdateResult(
-                    NewTabPageUma.ContentSuggestionsUIUpdateResult.SUCCESS_APPENDED);
-            mHasAppended = true;
-        } else {
-            NewTabPageUma.recordNumberOfSuggestionsSeenBeforeUIUpdateSuccess(
-                    numberOfSuggestionsExposed);
-            NewTabPageUma.recordUIUpdateResult(
-                    NewTabPageUma.ContentSuggestionsUIUpdateResult.SUCCESS_REPLACED);
-        }
+        if (!keepSectionSize) mHasAppended = true;
     }
 
     /**
@@ -423,8 +413,6 @@
 
         if (CardsVariationParameters.ignoreUpdatesForExistingSuggestions()) {
             Log.d(TAG, "updateModels: replacing existing suggestion disabled");
-            NewTabPageUma.recordUIUpdateResult(
-                    NewTabPageUma.ContentSuggestionsUIUpdateResult.FAIL_DISABLED);
             return false;
         }
 
@@ -432,8 +420,6 @@
             // In case that suggestions got removed, we assume they already were seen. This might
             // be over-simplifying things, but given the rare occurences it should be good enough.
             Log.d(TAG, "updateModels: replacing existing suggestion not possible, all seen");
-            NewTabPageUma.recordUIUpdateResult(
-                    NewTabPageUma.ContentSuggestionsUIUpdateResult.FAIL_ALL_SEEN);
             return false;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java
index a8a805ccb..fb063131 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinder.java
@@ -15,7 +15,6 @@
 
 import org.chromium.base.Log;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.payments.PaymentManifestVerifier.ManifestVerifyCallback;
 import org.chromium.components.payments.MethodStrings;
 import org.chromium.components.payments.PaymentManifestDownloader;
@@ -23,6 +22,7 @@
 import org.chromium.components.payments.intent.WebPaymentIntentHelper;
 import org.chromium.payments.mojom.PaymentDetailsModifier;
 import org.chromium.payments.mojom.PaymentMethodData;
+import org.chromium.url.GURL;
 import org.chromium.url.URI;
 
 import java.util.ArrayList;
@@ -69,12 +69,6 @@
     /* package */ static final String META_DATA_NAME_OF_SUPPORTED_DELEGATIONS =
             "org.chromium.payment_supported_delegations";
 
-    /*
-     * The ignored payment method identifiers. Payment apps with this payment method identifier are
-     * ignored.
-     */
-    private final Set<String> mIgnoredMethods = new HashSet<>();
-
     private final Set<String> mNonUriPaymentMethods = new HashSet<>();
     private final Set<URI> mUriPaymentMethods = new HashSet<>();
     private final PaymentManifestDownloader mDownloader;
@@ -86,10 +80,13 @@
     private final boolean mIsIncognito;
 
     /**
-     * A map from an app-store app's package name to its billing method. All of the supported
-     * app-store billing method must insert an entry to this map.
+     * The app stores that supports app-store billing methods.
+     *
+     * key: the app-store app's package name, e.g., "com.google.vendor" (Google Play Store).
+     * value: the app-store app's billing method identifier, e.g.,
+     * "https://play.google.com/billing". Only valid GURLs are allowed.
      */
-    private final Map<String, String> mAppStoreBillingMethodMap = new HashMap();
+    private final Map<String, GURL> mAppStores = new HashMap();
 
     /**
      * A mapping from an Android package name to the payment app with that package name. The apps
@@ -173,9 +170,10 @@
             PaymentAppFactoryInterface factory) {
         mDelegate = delegate;
 
-        mIgnoredMethods.add(MethodStrings.GOOGLE_PLAY_BILLING);
-
-        mAppStoreBillingMethodMap.put(PLAY_STORE_PACKAGE_NAME, MethodStrings.GOOGLE_PLAY_BILLING);
+        mAppStores.put(PLAY_STORE_PACKAGE_NAME, new GURL(MethodStrings.GOOGLE_PLAY_BILLING));
+        for (GURL method : mAppStores.values()) {
+            assert method.isValid();
+        }
 
         mDownloader = downloader;
         mWebDataService = webDataService;
@@ -187,19 +185,62 @@
         mIsIncognito = activity != null && activity.getCurrentTabModel().isIncognito();
     }
 
-    private boolean isInTwaInstalledFromAppStore() {
-        ChromeActivity activity =
-                ChromeActivity.fromWebContents(mDelegate.getParams().getWebContents());
-        if (activity == null) return false;
-        if (!(activity instanceof CustomTabActivity)) return false;
-        CustomTabActivity customTabActivity = ((CustomTabActivity) activity);
-        if (!customTabActivity.isInTwaMode()) return false;
-        String twaPackageName = customTabActivity.getTwaPackage();
+    private boolean isInTwaInstalledFromAppStore(ChromeActivity activity) {
+        assert activity != null;
+        String twaPackageName = mPackageManagerDelegate.getTwaPackageName(activity);
         if (twaPackageName == null) return false;
-        String installerPackageName =
-                activity.getPackageManager().getInstallerPackageName(twaPackageName);
+        String installerPackageName = mPackageManagerDelegate.getInstallerPackage(twaPackageName);
         if (installerPackageName == null) return false;
-        return mAppStoreBillingMethodMap.keySet().contains(installerPackageName);
+        return mAppStores.containsKey(installerPackageName);
+    }
+
+    /** Precondition: {@link #isInTwaInstalledFromAppStore} returns true. */
+    private void findAppStoreBillingApp(
+            ChromeActivity activity, List<ResolveInfo> allInstalledPaymentApps) {
+        assert activity != null;
+        // The following asserts are assumed to have been checked in {@link
+        // isInTwaInstalledFromAppStore}.
+        String twaPackageName = mPackageManagerDelegate.getTwaPackageName(activity);
+        assert twaPackageName != null;
+        String installerAppStorePackageName =
+                mPackageManagerDelegate.getInstallerPackage(twaPackageName);
+        assert installerAppStorePackageName != null;
+
+        GURL appStoreBillingUriMethod = mAppStores.get(installerAppStorePackageName);
+        assert appStoreBillingUriMethod != null;
+        assert appStoreBillingUriMethod.isValid();
+        String appStoreBillingMethod = appStoreBillingUriMethod.getSpec();
+        if (!mDelegate.getParams().getMethodData().containsKey(appStoreBillingMethod)) return;
+        ResolveInfo twaApp = findAppWithPackageNameAndSupportedMethod(
+                allInstalledPaymentApps, twaPackageName, appStoreBillingUriMethod);
+        if (twaApp == null) {
+            android.util.Log.d(TAG, "The current TWA cannot handle Payment Request.");
+            return;
+        }
+        onValidPaymentAppForPaymentMethodName(twaApp, appStoreBillingMethod);
+    }
+
+    private ResolveInfo findAppWithPackageNameAndSupportedMethod(
+            List<ResolveInfo> apps, String packageName, GURL uriMethod) {
+        assert packageName != null;
+        assert uriMethod != null;
+        for (int i = 0; i < apps.size(); i++) {
+            ResolveInfo app = apps.get(i);
+            String appPackageName = app.activityInfo.packageName;
+            if (!packageName.equals(appPackageName)) continue;
+            String defaultMethod = app.activityInfo.metaData == null
+                    ? null
+                    : app.activityInfo.metaData.getString(
+                            META_DATA_NAME_OF_DEFAULT_PAYMENT_METHOD_NAME);
+            GURL defaultUriMethod = new GURL(defaultMethod);
+            if ((uriMethod.isValid()
+                        && getSupportedPaymentMethods(app.activityInfo)
+                                   .contains(uriMethod.getSpec()))
+                    || (defaultUriMethod.isValid() && uriMethod.equals(defaultUriMethod))) {
+                return app;
+            }
+        }
+        return null;
     }
 
     /**
@@ -218,7 +259,7 @@
 
         for (String method : mDelegate.getParams().getMethodData().keySet()) {
             assert !TextUtils.isEmpty(method);
-            if (mIgnoredMethods.contains(method)) continue;
+            if (mAppStores.containsValue(new GURL(method))) continue;
             if (supportedNonUriPaymentMethods.contains(method)) {
                 mNonUriPaymentMethods.add(method);
             } else if (UriUtils.looksLikeUriMethod(method)) {
@@ -245,9 +286,17 @@
             }
         }
 
-        if (isInTwaInstalledFromAppStore()) {
-            // TODO(crbug.com/1064740): the finder would special-case the TWA installed from App
-            // Store to return only the app-store app.
+        // WebContents is possible to attach to different activities on {@link PaymentRequest}
+        // created and shown. Ideally {@link #findAppStoreBillingApp} should have based on the
+        // activity that is used when PaymentRequest is shown. But we intentionally not do that for
+        // the sake of simple design and better performance. Plus, for app store billing case in
+        // particular, it's unusual for a TWA to switch to CCT without destroying JavaScript context
+        // and, consequently, the {@link PaymentRequest} object.
+        ChromeActivity activity =
+                ChromeActivity.fromWebContents(mDelegate.getParams().getWebContents());
+        if (!mDelegate.getParams().requestShippingOrPayerContact() && activity != null
+                && isInTwaInstalledFromAppStore(activity)) {
+            findAppStoreBillingApp(activity, allInstalledPaymentApps);
         }
 
         // All URI methods for which manifests should be downloaded. For example, if merchant
@@ -646,14 +695,14 @@
     }
 
     /**
-     * Ignores the given payment method identifier, so no Android payment apps for this method are
-     * looked up in findAndroidPaymentApps(). Calling this multiple times will union the new payment
-     * methods with the existing set.
+     * Add an app store for testing.
      *
-     * @param ignoredPaymentMethodIdentifier The ignored payment method identifier.
+     * @param packageName The package name of the app store.
+     * @param paymentMethod The payment method identifier of the app store.
      */
     @VisibleForTesting
-    /* package */ void ignorePaymentMethodForTest(String ignoredPaymentMethodIdentifier) {
-        mIgnoredMethods.add(ignoredPaymentMethodIdentifier);
+    /* package */ void addAppStoreForTest(String packageName, GURL paymentMethod) {
+        assert paymentMethod.isValid();
+        mAppStores.put(packageName, paymentMethod);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PackageManagerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PackageManagerDelegate.java
index 1eb4ec8f..4cc4de2c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PackageManagerDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PackageManagerDelegate.java
@@ -20,6 +20,8 @@
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.PackageManagerUtils;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 
 import java.util.List;
 
@@ -123,4 +125,31 @@
         }
         return resources == null ? null : resources.getStringArray(resourceId);
     }
+
+    /**
+     * Get the package name of an activity if it is a Trusted Web Activity.
+     * @param activity An activity that is intended to check whether its a Trusted Web Activity and
+     *         get the package name from. Not allowed to be null.
+     * @return The package name of a given activity if it is a Trusted Web Activity; null otherwise.
+     */
+    @Nullable
+    public String getTwaPackageName(ChromeActivity activity) {
+        assert activity != null;
+        if (!(activity instanceof CustomTabActivity)) return null;
+        CustomTabActivity customTabActivity = ((CustomTabActivity) activity);
+        if (!customTabActivity.isInTwaMode()) return null;
+        return customTabActivity.getTwaPackage();
+    }
+
+    /**
+     * Get the package name of a specified package's installer app.
+     * @param packageName The package name of the specified package. Not allowed to be null.
+     * @return The package name of the installer app.
+     */
+    @Nullable
+    public String getInstallerPackage(String packageName) {
+        assert packageName != null;
+        return ContextUtils.getApplicationContext().getPackageManager().getInstallerPackageName(
+                packageName);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryParams.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryParams.java
index 49f0b43..3114bb5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryParams.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryParams.java
@@ -95,4 +95,12 @@
     default String getTotalAmountCurrency() {
         return null;
     }
+
+    /**
+     * @return Whether the PaymentRequest is requesting delegation of either shipping or payer
+     *         contact.
+     */
+    default boolean requestShippingOrPayerContact() {
+        return false;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
index 4de2a31..97da8763 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -2620,6 +2620,12 @@
         return mRawTotal.amount.currency;
     }
 
+    // PaymentAppFactoryParams implementation.
+    @Override
+    public boolean requestShippingOrPayerContact() {
+        return mRequestShipping || mRequestPayerName || mRequestPayerPhone || mRequestPayerEmail;
+    }
+
     // PaymentAppFactoryDelegate implementation.
     @Override
     public PaymentAppFactoryParams getParams() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java
index 6c4a273..5801be0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java
@@ -124,8 +124,6 @@
                 PUBLISHER_FAVICON_DESIRED_SIZE_PX, new Callback<Bitmap>() {
                     @Override
                     public void onResult(Bitmap image) {
-                        SuggestionsMetrics.recordArticleFaviconFetchTime(
-                                SystemClock.elapsedRealtime() - faviconFetchStartTimeMs);
                         if (image == null) return;
                         faviconCallback.onResult(image);
                     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java
index 7108710..75cbffd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsMetrics.java
@@ -11,7 +11,6 @@
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.ntp.cards.ActionItem.State;
 import org.chromium.chrome.browser.ntp.snippets.CategoryInt;
-import org.chromium.chrome.browser.ntp.snippets.FaviconFetchResult;
 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.Pref;
@@ -108,17 +107,6 @@
     }
 
     /**
-     * Records the result from a favicon fetch for an article.
-     *
-     * @param result {@link FaviconFetchResult} The result from the fetch.
-     */
-    public static void recordArticleFaviconFetchResult(@FaviconFetchResult int result) {
-        RecordHistogram.recordEnumeratedHistogram(
-                "NewTabPage.ContentSuggestions.ArticleFaviconFetchResult", result,
-                FaviconFetchResult.COUNT);
-    }
-
-    /**
      * Records which tiles are available offline once the site suggestions finished loading.
      * @param tileIndex index of a tile whose URL is available offline.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelper.java
new file mode 100644
index 0000000..c2d0f56
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelper.java
@@ -0,0 +1,151 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.suggestions.mostvisited;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+
+import androidx.core.util.AtomicFile;
+
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.Log;
+import org.chromium.base.task.AsyncTask;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.suggestions.SiteSuggestion;
+import org.chromium.chrome.browser.ui.favicon.IconType;
+import org.chromium.chrome.browser.ui.favicon.LargeIconBridge;
+import org.chromium.chrome.browser.ui.favicon.RoundedIconGenerator;
+import org.chromium.url.GURL;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class provides methods to fetch/save most visited sites favicon info to devices.
+ */
+public class MostVisitedSitesFaviconHelper {
+    private static final String TAG = "TopSitesFavicon";
+
+    private final int mMinIconSize;
+    private final int mDesiredIconSize;
+    private final LargeIconBridge mLargeIconBridge;
+    private final RoundedIconGenerator mIconGenerator;
+
+    public MostVisitedSitesFaviconHelper(Context context, LargeIconBridge largeIconBridge) {
+        mLargeIconBridge = largeIconBridge;
+        Resources resources = context.getResources();
+
+        mDesiredIconSize = resources.getDimensionPixelSize(R.dimen.tile_view_icon_size);
+        int minIconSize = resources.getDimensionPixelSize(R.dimen.tile_view_icon_min_size);
+        // On ldpi devices, mDesiredIconSize could be even smaller than the global limit.
+        mMinIconSize = Math.min(mDesiredIconSize, minIconSize);
+
+        int iconColor =
+                ApiCompatibilityUtils.getColor(resources, R.color.default_favicon_background_color);
+        int iconTextSize = resources.getDimensionPixelSize(R.dimen.tile_view_icon_text_size);
+        mIconGenerator = new RoundedIconGenerator(
+                mDesiredIconSize, mDesiredIconSize, mDesiredIconSize / 2, iconColor, iconTextSize);
+    }
+
+    /**
+     * Save the favicon to the disk.
+     * @param topSitesInfo SiteSuggestions data updated.
+     * @param urlsToUpdate The set of urls which need to fetch and save the favicon.
+     */
+    public void saveFaviconsToFile(List<SiteSuggestion> topSitesInfo, Set<String> urlsToUpdate) {
+        for (SiteSuggestion siteData : topSitesInfo) {
+            String url = siteData.url;
+            if (!urlsToUpdate.contains(url)) {
+                continue;
+            }
+            LargeIconBridge.LargeIconCallback iconCallback =
+                    (icon, fallbackColor, isFallbackColorDefault, iconType) -> {
+                saveFaviconToFile(String.valueOf(siteData.faviconId),
+                        MostVisitedSitesMetadataUtils.getOrCreateTopSitesDirectory(), url,
+                        fallbackColor, icon);
+            };
+            fetchIcon(siteData, iconCallback);
+        }
+    }
+
+    /**
+     * Fetch the favicon for a given site.
+     * @param siteData SiteSuggestion data which needs to fetch and save the favicon.
+     * @param iconCallback  The callback function after fetching the favicon.
+     */
+    // TODO(https://crbug.com/1067386): Change fetchIcon() to public and static, then reuse it in
+    // other classes.
+    private void fetchIcon(
+            final SiteSuggestion siteData, final LargeIconBridge.LargeIconCallback iconCallback) {
+        if (siteData.whitelistIconPath.isEmpty()) {
+            mLargeIconBridge.getLargeIconForUrl(new GURL(siteData.url), mMinIconSize, iconCallback);
+            return;
+        }
+
+        AsyncTask<Bitmap> task = new AsyncTask<Bitmap>() {
+            @Override
+            protected Bitmap doInBackground() {
+                Bitmap bitmap = BitmapFactory.decodeFile(siteData.whitelistIconPath);
+                if (bitmap == null) {
+                    Log.d(TAG, "Image decoding failed: %s.", siteData.whitelistIconPath);
+                }
+                return bitmap;
+            }
+
+            @Override
+            protected void onPostExecute(Bitmap icon) {
+                if (icon == null) {
+                    mLargeIconBridge.getLargeIconForUrl(
+                            new GURL(siteData.url), mMinIconSize, iconCallback);
+                } else {
+                    iconCallback.onLargeIconAvailable(icon, Color.BLACK, false, IconType.INVALID);
+                }
+            }
+        };
+        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
+    /**
+     * Save the favicon to the disk.
+     * @param fileName The file name to save the favicon.
+     * @param directory The directory to save the favicon.
+     * @param url The url which the favicon corresponds to.
+     * @param fallbackColor The color for generating a new icon when favicon is null from native.
+     * @param icon The favicon fetched from native.
+     */
+    private void saveFaviconToFile(
+            String fileName, File directory, String url, int fallbackColor, Bitmap icon) {
+        AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
+            Bitmap newIcon = icon;
+            // If icon is null, we need to generate a favicon.
+            if (newIcon == null) {
+                Log.i(TAG, "Favicon is null for " + url + ". Generating an icon for it.");
+                mIconGenerator.setBackgroundColor(fallbackColor);
+                newIcon = mIconGenerator.generateIconForUrl(url);
+            }
+            // Save icon to file.
+            File metadataFile = new File(directory, fileName);
+            AtomicFile file = new AtomicFile(metadataFile);
+            FileOutputStream stream;
+            try {
+                stream = file.startWrite();
+                assert newIcon != null;
+                newIcon.compress(Bitmap.CompressFormat.PNG, 100, stream);
+                file.finishWrite(stream);
+                Log.i(TAG,
+                        "Finished saving top sites favicons to file: "
+                                + metadataFile.getAbsolutePath());
+            } catch (IOException e) {
+                Log.e(TAG, "Fail to write file: " + metadataFile.getAbsolutePath());
+            }
+        });
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtils.java
index d3c4645..982f739 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesMetadataUtils.java
@@ -6,6 +6,7 @@
 
 import android.content.Context;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.core.util.AtomicFile;
 
 import org.chromium.base.ContextUtils;
@@ -209,4 +210,9 @@
             return sStateDirectory;
         }
     }
+
+    @VisibleForTesting
+    protected static File getStateDirectoryForTesting() {
+        return sStateDirectory;
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java
index 768f29f..fb6ce61 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java
@@ -14,6 +14,7 @@
 import android.support.test.filters.MediumTest;
 import android.support.test.filters.SmallTest;
 
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
@@ -87,6 +88,11 @@
         mTabModelSelector.addObserver(tabModelSelectorObserver);
     }
 
+    @After
+    public void tearDown() {
+        LauncherShortcutActivity.setDynamicShortcutStringForTesting(null);
+    }
+
     @Test
     @MediumTest
     @ParameterAnnotations.UseMethodParameter(IncognitoParams.class)
@@ -169,4 +175,25 @@
         Assert.assertEquals("Incorrect number of dynamic shortcuts after re-enabling incognito.", 1,
                 shortcuts.size());
     }
+
+    @Test
+    @SmallTest
+    public void testDynamicShortcuts_LanguageChange() {
+        IncognitoUtils.setEnabledForTesting(true);
+        LauncherShortcutActivity.updateIncognitoShortcut(mActivityTestRule.getActivity());
+        ShortcutManager shortcutManager =
+                mActivityTestRule.getActivity().getSystemService(ShortcutManager.class);
+        List<ShortcutInfo> shortcuts = shortcutManager.getDynamicShortcuts();
+        Assert.assertEquals("Incorrect number of dynamic shortcuts.", 1, shortcuts.size());
+        Assert.assertEquals(
+                "Incorrect label", "New incognito tab", shortcuts.get(0).getLongLabel());
+
+        LauncherShortcutActivity.setDynamicShortcutStringForTesting("Foo");
+        LauncherShortcutActivity.updateIncognitoShortcut(mActivityTestRule.getActivity());
+        shortcuts = shortcutManager.getDynamicShortcuts();
+        Assert.assertEquals(
+                "Incorrect number of dynamic shortcuts after updating.", 1, shortcuts.size());
+        Assert.assertEquals(
+                "Incorrect label after updating.", "Foo", shortcuts.get(0).getLongLabel());
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
index 427795f..ccfdaec 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -214,7 +214,6 @@
     }
 
     @Test
-    @DisabledTest(message = "https://crbug.com/888129")
     @SmallTest
     @Feature({"NewTabPage", "FeedNewTabPage", "RenderTest"})
     @ParameterAnnotations.UseMethodParameter(InterestFeedParams.class)
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java
index 44cd642..2f20e2d2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java
@@ -29,15 +29,18 @@
 import org.chromium.net.test.EmbeddedTestServer;
 import org.chromium.payments.mojom.PaymentDetailsModifier;
 import org.chromium.payments.mojom.PaymentMethodData;
+import org.chromium.url.GURL;
 import org.chromium.url.Origin;
 import org.chromium.url.URI;
 
 import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
@@ -96,6 +99,7 @@
     private List<PaymentApp> mPaymentApps;
     private boolean mAllPaymentAppsCreated;
     private Map<String, PaymentMethodData> mMethodData;
+    private boolean mRequestShippingOrPayerContact;
 
     // PaymentAppFactoryDelegate implementation.
     @Override
@@ -161,6 +165,12 @@
         return mMethodData;
     }
 
+    // PaymentAppFactoryParams implementation.
+    @Override
+    public boolean requestShippingOrPayerContact() {
+        return mRequestShippingOrPayerContact;
+    }
+
     @Before
     public void setUp() throws Throwable {
         mRule.startMainActivityOnBlankPage();
@@ -371,17 +381,17 @@
         Assert.assertEquals("com.bobpay", mPaymentApps.get(0).getIdentifier());
     }
 
-    /** Ignored payment methods should be filtered out. */
+    /** When Chrome is not running in TWA, the app store billing methods should be filtered out. */
     @Test
     @Feature({"Payments"})
-    public void testIgnoredPaymentMethodIdentifier() throws Throwable {
+    public void testIgnoreAppStoreMethodsInNonTwa() throws Throwable {
         Set<String> methods = new HashSet<>();
         methods.add("https://bobpay.com/webpay");
         mPackageManager.installPaymentApp("BobPay", "com.bobpay", "https://bobpay.com/webpay",
                 /*signature=*/"01020304050607080900");
 
-        ignorePaymentMethodIdentifierAndFindApps(
-                /*ignoredPaymentMethodIdentifier=*/"https://bobpay.com/webpay", methods);
+        addAppStoreMethodAndFindApps(/*appStorePackageName=*/"com.bobpay",
+                /*appStorePaymentMethod=*/new GURL("https://bobpay.com/webpay"), methods);
 
         Assert.assertTrue("No apps should match the query", mPaymentApps.isEmpty());
     }
@@ -1091,6 +1101,230 @@
     }
 
     /**
+     * The basic test for {@link AndroidPaymentAppFinder#findAndroidPaymentApps} to find a app-store
+     * (e.g., Google Store) billing app.
+     */
+    @Test
+    @Feature({"Payments"})
+    public void testFindAppStoreBillingApp() throws Throwable {
+        Set<String> methods = new HashSet<>();
+        methods.add("https://play.google.com/billing");
+        mPackageManager.installPaymentApp("MerchantTwaApp", "com.merchant.twa",
+                "https://play.google.com/billing", /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.merchant.twa", new String[] {"https://play.google.com/billing"});
+
+        mockTwaAndItsInstaller("com.merchant.twa", "com.android.vending");
+        findApps(methods);
+
+        Assert.assertEquals("1 app should still match the query", 1, mPaymentApps.size());
+        Assert.assertEquals("com.merchant.twa", mPaymentApps.get(0).getIdentifier());
+    }
+
+    /**
+     * For finding app store billing app, test that the TWA only has default app store but no
+     * support the billing method in its Android manifest. The test setting intentionally omits the
+     * setting of the twa's supported methods.
+     */
+    @Test
+    @Feature({"Payments"})
+    public void testFindAppStoreBillingAppTwaHasDefaultAppStoreMethod() throws Throwable {
+        Set<String> methods = new HashSet<>();
+        methods.add("https://play.google.com/billing");
+        mPackageManager.installPaymentApp("MerchantTwaApp", "com.merchant.twa",
+                "https://play.google.com/billing", /*signature=*/"01020304050607080900");
+
+        mockTwaAndItsInstaller("com.merchant.twa", "com.android.vending");
+        findApps(methods);
+
+        Assert.assertEquals("1 app should still match the query", 1, mPaymentApps.size());
+        Assert.assertEquals("com.merchant.twa", mPaymentApps.get(0).getIdentifier());
+    }
+
+    /**
+     * For finding app store billing app, test that the TWA has support the billing method but no
+     * default method in its manifest. The test setting intentionally set TWA's default method to a
+     * non-store method.
+     */
+    @Test
+    @Feature({"Payments"})
+    public void testFindAppStoreBillingAppTwaHasSupportedAppStoreMethod() throws Throwable {
+        Set<String> methods = new HashSet<>();
+        methods.add("https://play.google.com/billing");
+        mPackageManager.installPaymentApp("MerchantTwaApp", "com.merchant.twa", "an://invalid.url",
+                /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.merchant.twa", new String[] {"https://play.google.com/billing"});
+
+        mockTwaAndItsInstaller("com.merchant.twa", "com.android.vending");
+        findApps(methods);
+
+        Assert.assertEquals("1 app should still match the query", 1, mPaymentApps.size());
+        Assert.assertEquals("com.merchant.twa", mPaymentApps.get(0).getIdentifier());
+    }
+
+    /**
+     * For finding app store billing app, test that the TWA's installer app store must be the same
+     * as the app store in the payment request. The test setting sets the twa installer app store to
+     * be a different one.
+     */
+    @Test
+    @Feature({"Payments"})
+    public void testFindAppStoreBillingAppMustFromSameAppStoreAsTheRequested() throws Throwable {
+        Set<String> methods = new HashSet<>();
+        methods.add("https://play.google.com/billing");
+        methods.add("https://bobpay.com/webpay");
+        mPackageManager.installPaymentApp("MerchantTwaApp", "com.merchant.twa",
+                "https://play.google.com/billing", /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.merchant.twa", new String[] {"https://play.google.com/billing"});
+        mPackageManager.installPaymentApp("BobPay", "com.bobpay", "https://bobpay.com/webpay",
+                /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.bobpay", new String[] {"https://bobpay.com/webpay"});
+
+        mockTwaAndItsInstaller("com.merchant.twa", "com.another.appstore");
+        findApps(methods);
+
+        Assert.assertEquals("1 app should still match the query", 1, mPaymentApps.size());
+        Assert.assertEquals("com.bobpay", mPaymentApps.get(0).getIdentifier());
+    }
+
+    /**
+     * For finding app store billing app, test that the TWA's installer app store must be a
+     * whitelisted one. The test setting sets the twa installer app store to be an unsupported one.
+     */
+    @Test
+    @Feature({"Payments"})
+    public void testFindAppStoreBillingAppMustInSupportedAppStore() throws Throwable {
+        Set<String> methods = new HashSet<>();
+        methods.add("https://another.playstore.com/billing");
+        methods.add("https://bobpay.com/webpay");
+        mPackageManager.installPaymentApp("MerchantTwaApp", "com.merchant.twa",
+                "https://another.playstore.com/billing", /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.merchant.twa", new String[] {"https://another.playstore.com/billing"});
+        mPackageManager.installPaymentApp("BobPay", "com.bobpay", "https://bobpay.com/webpay",
+                /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.bobpay", new String[] {"https://bobpay.com/webpay"});
+
+        mockTwaAndItsInstaller("com.merchant.twa", "com.another.appstore");
+        findApps(methods);
+
+        Assert.assertEquals("1 app should still match the query", 1, mPaymentApps.size());
+        Assert.assertEquals("com.bobpay", mPaymentApps.get(0).getIdentifier());
+    }
+
+    /**
+     * For finding app store billing app, test that Chrome must be in TWA to use app store billing.
+     * The test setting intentionally omits the twa mocking.
+     */
+    @Test
+    @Feature({"Payments"})
+    public void testFindAppStoreBillingAppMustInTwa() throws Throwable {
+        Set<String> methods = new HashSet<>();
+        methods.add("https://play.google.com/billing");
+        methods.add("https://bobpay.com/webpay");
+
+        mPackageManager.installPaymentApp("MerchantTwaApp", "com.merchant.twa",
+                "https://play.google.com/billing", /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.merchant.twa", new String[] {"https://play.google.com/billing"});
+        mPackageManager.installPaymentApp("BobPay", "com.bobpay", "https://bobpay.com/webpay",
+                /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.bobpay", new String[] {"https://bobpay.com/webpay"});
+
+        findApps(methods);
+
+        Assert.assertEquals("1 app should still match the query", 1, mPaymentApps.size());
+        Assert.assertEquals("com.bobpay", mPaymentApps.get(0).getIdentifier());
+    }
+
+    /**
+     * For finding app store billing app, test that the payment request must support the app store
+     * billing method to be able to use it. The test setting intentionally omits the app store
+     * billing method in the payment request.
+     */
+    @Test
+    @Feature({"Payments"})
+    public void testFindAppStoreBillingAppNotRequested() throws Throwable {
+        Set<String> noRequestedMethod = new HashSet<>();
+        noRequestedMethod.add("https://bobpay.com/webpay");
+
+        mPackageManager.installPaymentApp("MerchantTwaApp", "com.merchant.twa",
+                "https://play.google.com/billing", /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.merchant.twa", new String[] {"https://play.google.com/billing"});
+        mPackageManager.installPaymentApp("BobPay", "com.bobpay", "https://bobpay.com/webpay",
+                /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.bobpay", new String[] {"https://bobpay.com/webpay"});
+
+        mockTwaAndItsInstaller("com.merchant.twa", "com.android.vending");
+        findApps(noRequestedMethod);
+
+        Assert.assertEquals("1 app should still match the query", 1, mPaymentApps.size());
+        Assert.assertEquals("com.bobpay", mPaymentApps.get(0).getIdentifier());
+    }
+
+    /**
+     * For finding app store billing app, test that once when Chrome starts to look for app store
+     * billing app, it ignores all other normal payment apps. The test setting includes a normal
+     * native payment method and play billing method, and expects to see the normal one is ignored.
+     */
+    @Test
+    @Feature({"Payments"})
+    public void testFindAppStoreBillingAppIgnoreNonAppStoreBillingApps() throws Throwable {
+        Set<String> methods = new HashSet<>();
+        methods.add("https://play.google.com/billing");
+        methods.add("https://bobpay.com/webpay");
+        mPackageManager.installPaymentApp("MerchantTwaApp", "com.merchant.twa",
+                "https://play.google.com/billing", /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.merchant.twa", new String[] {"https://play.google.com/billing"});
+        mPackageManager.installPaymentApp("BobPay", "com.bobpay", "https://bobpay.com/webpay",
+                /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.bobpay", new String[] {"https://bobpay.com/webpay"});
+
+        mockTwaAndItsInstaller("com.merchant.twa", "com.android.vending");
+        findApps(methods);
+
+        assertPaymentAppsHaveIdentifiers("com.merchant.twa", "com.bobpay");
+    }
+
+    /**
+     * For finding app store billing app, test that if delegation is requested along with the
+     * app-store billing method, the app-store billing method would be ignore. The test setting
+     * requests the shipping or payer contact delegation.
+     */
+    @Test
+    @Feature({"Payments"})
+    public void testFindAppStoreBillingAppDelegationRejectBilling() throws Throwable {
+        Set<String> methods = new HashSet<>();
+        methods.add("https://play.google.com/billing");
+        methods.add("https://bobpay.com/webpay");
+        mRequestShippingOrPayerContact = true;
+        mPackageManager.installPaymentApp("MerchantTwaApp", "com.merchant.twa",
+                "https://play.google.com/billing",
+                /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.merchant.twa", new String[] {"https://play.google.com/billing"});
+        mPackageManager.installPaymentApp("BobPay", "com.bobpay", "https://bobpay.com/webpay",
+                /*signature=*/"01020304050607080900");
+        mPackageManager.setStringArrayMetaData(
+                "com.bobpay", new String[] {"https://bobpay.com/webpay"});
+
+        mockTwaAndItsInstaller("com.merchant.twa", "com.android.vending");
+        findApps(methods);
+
+        Assert.assertEquals("1 app should still match the query", 1, mPaymentApps.size());
+        Assert.assertEquals("com.bobpay", mPaymentApps.get(0).getIdentifier());
+    }
+
+    /**
      * If a payment method supports two apps from different origins, both apps should be found.
      * Repeated app look ups should succeed.
      */
@@ -1231,12 +1465,12 @@
     }
 
     private void findApps(Set<String> methodNames) throws Throwable {
-        ignorePaymentMethodIdentifierAndFindApps(
-                /*ignoredPaymentMethodIdentifier=*/null, methodNames);
+        addAppStoreMethodAndFindApps(
+                /*appStorePackageName=*/null, /*appStorePaymentMethod=*/null, methodNames);
     }
 
-    private void ignorePaymentMethodIdentifierAndFindApps(
-            String ignoredPaymentMethodIdentifier, Set<String> methodNames) throws Throwable {
+    private void addAppStoreMethodAndFindApps(String appStorePackageName,
+            GURL appStorePaymentMethod, Set<String> methodNames) throws Throwable {
         mMethodData = buildMethodData(methodNames);
         mRule.runOnUiThread(() -> {
             AndroidPaymentAppFinder finder =
@@ -1244,8 +1478,10 @@
                             new PaymentManifestParser(), mPackageManager,
                             /*delegate=*/AndroidPaymentAppFinderTest.this, /*factory=*/null);
             finder.bypassIsReadyToPayServiceInTest();
-            if (ignoredPaymentMethodIdentifier != null) {
-                finder.ignorePaymentMethodForTest(ignoredPaymentMethodIdentifier);
+            if (appStorePackageName != null) {
+                assert appStorePaymentMethod != null;
+                assert appStorePaymentMethod.isValid();
+                finder.addAppStoreForTest(appStorePackageName, appStorePaymentMethod);
             }
             finder.findAndroidPaymentApps();
         });
@@ -1266,4 +1502,28 @@
         }
         return result;
     }
+
+    private void mockTwaAndItsInstaller(String twaPackageName, String installerPackageName) {
+        mPackageManager.setMockTrustedWebActivity(twaPackageName);
+        mPackageManager.mockInstallerForPackage(twaPackageName, installerPackageName);
+    }
+
+    private void assertPaymentAppsHaveIdentifiers(String... expectedIds) {
+        Set<String> ids = new HashSet<>();
+        for (PaymentApp app : mPaymentApps) {
+            ids.add(app.getIdentifier());
+        }
+        Assert.assertEquals(
+                String.format(Locale.getDefault(), "Expected %d apps, but got %d apps instead.",
+                        expectedIds.length, ids.size()),
+                expectedIds.length, ids.size());
+        for (String expectedId : expectedIds) {
+            Assert.assertTrue(String.format(Locale.getDefault(),
+                                      "Expected id %s is not found. "
+                                              + "Expected identifiers: %s. "
+                                              + "Actual identifiers: %s",
+                                      expectedId, Arrays.toString(expectedIds), ids.toString()),
+                    ids.contains(expectedId));
+        }
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/MockPackageManagerDelegate.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/MockPackageManagerDelegate.java
index b17aa6c4..a12ecce 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/MockPackageManagerDelegate.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/MockPackageManagerDelegate.java
@@ -16,6 +16,8 @@
 
 import androidx.annotation.Nullable;
 
+import org.chromium.chrome.browser.ChromeActivity;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -31,6 +33,10 @@
     private final List<ResolveInfo> mServices = new ArrayList<>();
     private final Map<ApplicationInfo, String[]> mResources = new HashMap<>();
 
+    private String mMockTwaPackage;
+    // A map of a package name to its installer's package name.
+    private Map<String, String> mMockInstallerPackageMap = new HashMap<>();
+
     /**
      * Simulates an installed payment app with no supported delegations.
      *
@@ -140,6 +146,27 @@
         mLabels.clear();
     }
 
+    /**
+     * Mock the current package to be a Trust Web Activity package.
+     * @param mockTwaPackage The intended package nam, not allowed to be null.
+     */
+    public void setMockTrustedWebActivity(String mockTwaPackage) {
+        assert mockTwaPackage != null;
+        mMockTwaPackage = mockTwaPackage;
+    }
+
+    /**
+     * Mock the installer of a specified package.
+     * @param packageName The package name that is intended to mock a installer for.
+     * @param installerPackageName The package name intended to be set as the installer of the
+     *         specified package. not allowed to be null.
+     */
+    public void mockInstallerForPackage(String packageName, String installerPackageName) {
+        assert installerPackageName != null;
+        assert packageName != null;
+        mMockInstallerPackageMap.put(packageName, installerPackageName);
+    }
+
     @Override
     public List<ResolveInfo> getActivitiesThatCanRespondToIntentWithMetaData(Intent intent) {
         return mActivities;
@@ -177,4 +204,17 @@
         assert STRING_ARRAY_RESOURCE_ID == resourceId;
         return mResources.get(applicationInfo);
     }
+
+    @Override
+    @Nullable
+    public String getInstallerPackage(String packageName) {
+        return !mMockInstallerPackageMap.isEmpty() ? mMockInstallerPackageMap.get(packageName)
+                                                   : super.getInstallerPackage(packageName);
+    }
+
+    @Override
+    @Nullable
+    public String getTwaPackageName(ChromeActivity activity) {
+        return mMockTwaPackage != null ? mMockTwaPackage : super.getTwaPackageName(activity);
+    }
 }
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelperTest.java
new file mode 100644
index 0000000..46b81949
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesFaviconHelperTest.java
@@ -0,0 +1,148 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.suggestions.mostvisited;
+
+import android.graphics.Bitmap;
+import android.support.test.filters.MediumTest;
+
+import androidx.core.util.AtomicFile;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+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.suggestions.SiteSuggestion;
+import org.chromium.chrome.browser.suggestions.tile.TileSectionType;
+import org.chromium.chrome.browser.suggestions.tile.TileSource;
+import org.chromium.chrome.browser.suggestions.tile.TileTitleSource;
+import org.chromium.chrome.browser.ui.favicon.LargeIconBridge;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.content_public.browser.test.util.Criteria;
+import org.chromium.content_public.browser.test.util.CriteriaHelper;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Instrumentation tests for {@link MostVisitedSitesFaviconHelper}.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+public class MostVisitedSitesFaviconHelperTest {
+    @Rule
+    public ChromeTabbedActivityTestRule mTestSetupRule = new ChromeTabbedActivityTestRule();
+
+    private List<SiteSuggestion> mExpectedSiteSuggestions;
+    private MostVisitedSitesFaviconHelper mMostVisitedSitesFaviconHelper;
+
+    @Before
+    public void setUp() {
+        mTestSetupRule.startMainActivityOnBlankPage();
+        mExpectedSiteSuggestions = createFakeSiteSuggestions();
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            LargeIconBridge largeIconBridge =
+                    new LargeIconBridge(Profile.getLastUsedRegularProfile());
+            mMostVisitedSitesFaviconHelper = new MostVisitedSitesFaviconHelper(
+                    mTestSetupRule.getActivity(), largeIconBridge);
+        });
+    }
+
+    @Test
+    @MediumTest
+    public void testSaveFaviconsToFile() {
+        // Add sites' URLs into the urlsToUpdate, except the last one.
+        Set<String> urlsToUpdate = new HashSet<>();
+        for (int i = 0; i < mExpectedSiteSuggestions.size() - 1; i++) {
+            urlsToUpdate.add(mExpectedSiteSuggestions.get(i).url);
+        }
+
+        // Save file count before saving favicons since there might be other files in the directory.
+        int originalFilesNum = getStateDirectorySize();
+
+        // Call saveFaviconsToFile.
+        TestThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> mMostVisitedSitesFaviconHelper.saveFaviconsToFile(
+                                mExpectedSiteSuggestions, urlsToUpdate));
+
+        // Wait util the file number equals to expected one.
+        CriteriaHelper.pollInstrumentationThread(Criteria.equals(
+                urlsToUpdate.size(), () -> getStateDirectorySize() - originalFilesNum));
+
+        // The Favicon File lists in the disk.
+        File topSitesDirectory = MostVisitedSitesMetadataUtils.getStateDirectoryForTesting();
+        Assert.assertNotNull(topSitesDirectory);
+        String[] faviconFiles = topSitesDirectory.list();
+        Assert.assertNotNull(faviconFiles);
+        Set<String> existingIconFiles = new HashSet<>(Arrays.asList(faviconFiles));
+
+        // Check whether each URL's favicon exist in the disk.
+        Assert.assertTrue(existingIconFiles.contains("0"));
+        Assert.assertTrue(existingIconFiles.contains("1"));
+        Assert.assertTrue(existingIconFiles.contains("2"));
+        Assert.assertFalse(existingIconFiles.contains("3"));
+    }
+
+    private static List<SiteSuggestion> createFakeSiteSuggestions() {
+        List<SiteSuggestion> siteSuggestions = new ArrayList<>();
+
+        siteSuggestions.add(new SiteSuggestion("0 TOP_SITES", "https://www.foo.com", "",
+                TileTitleSource.TITLE_TAG, TileSource.TOP_SITES, TileSectionType.PERSONALIZED,
+                new Date()));
+        siteSuggestions.add(new SiteSuggestion("1 WHITELIST", "https://www.bar.com",
+                "/not_exist.png", TileTitleSource.UNKNOWN, TileSource.WHITELIST,
+                TileSectionType.PERSONALIZED, new Date()));
+        siteSuggestions.add(new SiteSuggestion("2 TOP_SITES", "https://www.baz.com",
+                createBitmapAndWriteToFile(), TileTitleSource.UNKNOWN, TileSource.WHITELIST,
+                TileSectionType.PERSONALIZED, new Date()));
+        siteSuggestions.add(new SiteSuggestion("3 TOP_SITES", "https://www.qux.com", "",
+                TileTitleSource.UNKNOWN, TileSource.WHITELIST, TileSectionType.PERSONALIZED,
+                new Date()));
+        siteSuggestions.get(0).faviconId = 0;
+        siteSuggestions.get(1).faviconId = 1;
+        siteSuggestions.get(2).faviconId = 2;
+        siteSuggestions.get(3).faviconId = 3;
+        return siteSuggestions;
+    }
+
+    private static String createBitmapAndWriteToFile() {
+        final Bitmap testBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+        String fileName = "test.png";
+        // Save bitmap to file.
+        File metadataFile =
+                new File(MostVisitedSitesMetadataUtils.getOrCreateTopSitesDirectory(), fileName);
+        AtomicFile file = new AtomicFile(metadataFile);
+        FileOutputStream stream;
+        try {
+            stream = file.startWrite();
+            testBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
+            file.finishWrite(stream);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return metadataFile.getAbsolutePath();
+    }
+
+    private static int getStateDirectorySize() {
+        return Objects
+                .requireNonNull(MostVisitedSitesMetadataUtils.getStateDirectoryForTesting().list())
+                .length;
+    }
+}
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 9006c0e8..afb45040 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1295,6 +1295,21 @@
   <message name="IDS_CHROMEOS_NETWORK_ERROR_CERTIFICATES_NOT_LOADED" desc="Network error details in notifications: Certificates not loaded">
     Certificates not loaded
   </message>
+  <message name="IDS_NETWORK_ERROR_CANNOT_CHANGE_SHARED_CONFIG" desc="Network error message shown when attempting to change a shared network configuration if the operation is not allowed">
+    Changing shared network configurations is not allowed
+  </message>
+  <message name="IDS_NETWORK_ERROR_NO_USER_CERT" desc="In the network connect dialog, when creating a VPN or enterprise Wi-Fi connection, error message to display when no user certificates are installed.">
+    Please install a user certificate.
+  </message>
+  <message name="IDS_NETWORK_ERROR_POLICY_CONTROLLED" desc="Network error message shown when attempting to remove or illegally modify a policy controlled network">
+    Network is policy controlled
+  </message>
+  <message name="IDS_NETWORK_ERROR_PASSPHRASE_REQUIRED" desc="Network error message shown when a passphrase is required to connect to a network but was not supplied.">
+    Passphrase required
+  </message>
+  <message name="IDS_NETWORK_ERROR_UNKNOWN" desc="Network error message shown for an unknown or unexpected network configuration error">
+    Error configuring network
+  </message>
 
   <!-- Sync/sign-in error messages -->
   <message name="IDS_SIGNIN_ERROR_SECONDARY_ACCOUNT_BUBBLE_VIEW_TITLE" desc="Title in the sign-in error bubble view/notification for Chrome OS Secondary Accounts.">
@@ -4638,6 +4653,35 @@
     Password (optional)
   </message>
 
+  <!-- SMB File Shares -->
+  <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_URL" desc="Title for the input that lets users specify the name of an SMB URL.">
+    File share URL
+  </message>
+  <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_NAME" desc="Title for the input that lets users specify the display name of an SMB mount.">
+    Display name (optional)
+  </message>
+  <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_USERNAME" desc="Title for the input that lets users specify their username for an SMB share.">
+    Username (optional)
+  </message>
+  <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_PASSWORD" desc="Title for the input that lets users specify their password for an SMB Share.">
+    Password (optional)
+  </message>
+  <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_SAVE_CREDENTIALS" desc="Label for the checkbox input that lets users have the username/password for an SMB share saved for the next login.">
+    Remember sign-in info
+  </message>
+  <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_AUTHENTICATION_METHOD" desc="Title for the input that lets users specify their authentication method for an SMB Share.">
+    Authentication method
+  </message>
+  <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_STANDARD_AUTHENTICATION" desc="Authentication method option indicating that fields for username and password should be shown to the user.">
+    Standard
+  </message>
+  <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_KERBEROS_AUTHENTICATION" desc="Authentication method option to use a users Kerberos ticket to authenticate. Only availible for Active Directory users.">
+    SSO
+  </message>
+  <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_DISCOVERY_MESSAGE" desc="The message shown next to the loading spinner shown when searching for SMB shares.">
+    Looking for file shares
+  </message>
+
   <!-- Strings for Plugin VM -->
   <message name="IDS_PLUGIN_VM_APP_NAME" desc="Name of the 'Plugin VM' app.">
     Plugin VM
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index 28ba777..a6225d7 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -2083,6 +2083,18 @@
   <message name="IDS_SETTINGS_POWER_IDLE_LABEL" desc="In Device Settings > Power, label for behavior when device is idle.">
     When idle
   </message>
+  <message name="IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_LABEL" desc="In Device Settings > Power, label for behavior when device is idle.">
+    While charging
+  </message>
+  <message name="IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_ARIA_LABEL" desc="In Device Settings > Power, aria label for behavior when device is idle.">
+    Idle action while charging
+  </message>
+  <message name="IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_LABEL" desc="In Device Settings > Power, label for behavior when device is idle.">
+    While on battery
+  </message>
+  <message name="IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_ARIA_LABEL" desc="In Device Settings > Power, aria label for behavior when device is idle.">
+    Idle action while on battery
+  </message>
   <message name="IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF_SLEEP" desc="In Device Settings > Power, menu item for idle behavior that turns the screen off and later puts the device to sleep. String must be short enough to fit in a drop-down menu.">
     Sleep
   </message>
@@ -2526,6 +2538,24 @@
   <message name="IDS_SETTINGS_APPS_LINK_TEXT" desc="The label for the button which links to the App Management page.">
     Manage your apps
   </message>
+  <message name="IDS_SETTINGS_ANDROID_APPS_TITLE" desc="The title of Google Play Store (Arc++ / Android Apps) section.">
+    Google Play Store
+  </message>
+  <message name="IDS_SETTINGS_ANDROID_SETTINGS_TITLE" desc="The title of Android settings section in case Play Store app is not available.">
+    Android settings
+  </message>
+  <message name="IDS_SETTINGS_ANDROID_APPS_SUBTEXT" desc="Description for the section for enabling and managing Google Play Store (Android) apps.">
+    Install apps and games from Google Play on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. &lt;a target="_blank" href="<ph name="URL">$2<ex>https://google.com/</ex></ph>"&gt;Learn more&lt;/a&gt;
+  </message>
+  <!-- TODO(jamescook): Use device type instead of "Chromebook", which may
+        require changing ArcPlayTermsOfServiceConsent resource id handling. -->
+  <message name="IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE" desc="Describes what will happen if the user opts out of android apps.">
+    Apps you’ve downloaded from Google Play will be deleted from this Chromebook.
+    <ph name="LINE_BREAKS1">&lt;br&gt;&lt;br&gt;</ph>
+    Content you’ve purchased such as movies, TV shows, music, books, or other in-app purchases may also be deleted.
+    <ph name="LINE_BREAKS2">&lt;br&gt;&lt;br&gt;</ph>
+    This doesn’t affect apps or content on other devices.
+  </message>
 
   <!-- Storage -->
   <message name="IDS_SETTINGS_STORAGE_TITLE" desc="In Device Settings, the title for storage management.">
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_ARIA_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_ARIA_LABEL.png.sha1
new file mode 100644
index 0000000..f5d413b9
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_ARIA_LABEL.png.sha1
@@ -0,0 +1 @@
+cbb914df0880e038010a23ff4d8efa3221262fae
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_LABEL.png.sha1
new file mode 100644
index 0000000..f5d413b9
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_LABEL.png.sha1
@@ -0,0 +1 @@
+cbb914df0880e038010a23ff4d8efa3221262fae
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_ARIA_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_ARIA_LABEL.png.sha1
new file mode 100644
index 0000000..f5d413b9
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_ARIA_LABEL.png.sha1
@@ -0,0 +1 @@
+cbb914df0880e038010a23ff4d8efa3221262fae
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_LABEL.png.sha1
new file mode 100644
index 0000000..f5d413b9
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_LABEL.png.sha1
@@ -0,0 +1 @@
+cbb914df0880e038010a23ff4d8efa3221262fae
\ No newline at end of file
diff --git a/chrome/app/resources/chromium_strings_bn.xtb b/chrome/app/resources/chromium_strings_bn.xtb
index a7ba961..7888b7ca 100644
--- a/chrome/app/resources/chromium_strings_bn.xtb
+++ b/chrome/app/resources/chromium_strings_bn.xtb
@@ -126,6 +126,7 @@
 <translation id="6096348254544841612">Chromium কে কাস্টমাইজ এবং নিয়ন্ত্রণ করুন৷ আপডেট পাওয়া যাবে৷</translation>
 <translation id="6120345080069858279">Chromium আপনার Google অ্যাকাউন্টে এই পাসওয়ার্ডটি সেভ করবে। আপনাকে এটি মনে রাখতে হবে না।</translation>
 <translation id="6129621093834146363"><ph name="FILE_NAME" /> বিপজ্জনক, তাই Chromium এটিকে অবরুদ্ধ করেছে।</translation>
+<translation id="6134968993075716475">'Safe Browsing'-এর সুবিধা বন্ধ করা আছে। তবে এটি চালু রাখার জন্য Chromium আপনাকে সাজেস্ট করছে।</translation>
 <translation id="6212496753309875659">এই কম্পিউটারে ইতিমধ্যে Chromium-এর আরও একটি সাম্প্রতিক ভার্সন রয়েছে৷ যদি সফ্টওয়্যার কাজ না করে, দয়া করে Chromium আনইনস্টল করুন এবং আবার চেষ্টা করুন৷</translation>
 <translation id="6219195342503754812">{0,plural, =0{Chromium এখন আবার লঞ্চ হবে}=1{Chromium ১ সেকেন্ডের মধ্যে আবার লঞ্চ হবে}one{Chromium # সেকেন্ডের মধ্যে আবার লঞ্চ হবে}other{Chromium # সেকেন্ডের মধ্যে আবার লঞ্চ হবে}}</translation>
 <translation id="6248213926982192922">Chromium-কে ডিফল্ট ব্রাউজার করুন</translation>
diff --git a/chrome/app/resources/generated_resources_be.xtb b/chrome/app/resources/generated_resources_be.xtb
index 2212d12..2dc23b5 100644
--- a/chrome/app/resources/generated_resources_be.xtb
+++ b/chrome/app/resources/generated_resources_be.xtb
@@ -1505,7 +1505,7 @@
 <translation id="2987620471460279764">Тэкст, абагулены з іншай прылады</translation>
 <translation id="2989474696604907455">не далучана</translation>
 <translation id="2989786307324390836">Адзін двайковы сертыфікат з DER-шыфраваннем</translation>
-<translation id="2992931425024192067">Паказваць усё змесціва ў апавяшчэннях</translation>
+<translation id="2992931425024192067">Паказваць усе апавяшчэнні</translation>
 <translation id="2993517869960930405">Інфармацыя аб праграме</translation>
 <translation id="2996286169319737844">Даныя зашыфраваны з дапамогай фразы-пароля для сінхранізацыі. Шыфраванне не распаўсюджваецца на спосабы аплаты і адрасы з Google Pay.</translation>
 <translation id="2996722619877761919">Карашок па доўгім краі</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index e14e374..aedc13a6 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -824,6 +824,7 @@
 <translation id="2119349053129246860"><ph name="APP" /> এ খুলুন</translation>
 <translation id="2120297377148151361">অ্যাক্টিভিটি এবং ইন্টার‌্যাকশন</translation>
 <translation id="2120639962942052471"><ph name="PERMISSION" /> ব্লক করা হয়েছে</translation>
+<translation id="2121055421682309734">{COUNT,plural, =0{কুকি ব্লক করা আছে}=1{১টি ছাড়া বাকি সব সাইটের কুকি ব্লক করা আছে}one{{COUNT}টি ছাড়া বাকি সব সাইটের কুকি ব্লক করা আছে}other{{COUNT}টি ছাড়া বাকি সব সাইটের কুকি ব্লক করা আছে}}</translation>
 <translation id="2121825465123208577">ছোট বড় করুন</translation>
 <translation id="2122305276694332719">কোনও লুকানো নেটওয়ার্কে অটোমেটিক কানেক্ট করলে, অন্যরা আপনার ডিভাইস ও নেটওয়ার্কের কিছু সেটিংস দেখার সুযোগ পান। তাই, এটি সাজেস্ট করা হয় না।</translation>
 <translation id="2123766928840368256">অন্য কোনও ফাইল বেছে নিন</translation>
diff --git a/chrome/app/resources/generated_resources_eu.xtb b/chrome/app/resources/generated_resources_eu.xtb
index fe512f6..a09e3bf 100644
--- a/chrome/app/resources/generated_resources_eu.xtb
+++ b/chrome/app/resources/generated_resources_eu.xtb
@@ -4949,7 +4949,7 @@
 <translation id="7690294790491645610">Berretsi pasahitz berria</translation>
 <translation id="7690378713476594306">Aukeratu zerrendatik</translation>
 <translation id="7690853182226561458">Gehitu &amp;karpeta…</translation>
-<translation id="7691073721729883399">Ezin izan da muntatu aplikazio espezializatuaren etxe kriptografikoa.</translation>
+<translation id="7691073721729883399">Ezin izan da muntatu aplikazio espezializatuaren cryptohome-a.</translation>
 <translation id="7691077781194517083">Ezin da berrezarri segurtasun-giltza. <ph name="ERROR_CODE" /> errorea.</translation>
 <translation id="7696063401938172191">"<ph name="PHONE_NAME" />" telefonoan:</translation>
 <translation id="7698408911093959127">{COUNT,plural, =1{1 elementu dago laster-marken zerrendan}other{# elementu daude laster-marken zerrendan}}</translation>
diff --git a/chrome/app/resources/generated_resources_mk.xtb b/chrome/app/resources/generated_resources_mk.xtb
index 5d5fedee..e1382a5 100644
--- a/chrome/app/resources/generated_resources_mk.xtb
+++ b/chrome/app/resources/generated_resources_mk.xtb
@@ -1474,7 +1474,7 @@
 <translation id="2941112035454246133">Низок</translation>
 <translation id="2942560570858569904">Се чека…</translation>
 <translation id="2942581856830209953">Приспособете ја страницава</translation>
-<translation id="2944060181911631861">Испраќајте податоци за користење и дијагностика. Помогнете ни да го подобриме вашето искуство со Android со автоматско испраќање дијагностички и податоци за користењето на уредот и апликациите до Google. Овие податоци ќе ни помогнат околу стабилноста на системот и апликациите и за други подобрувања. Некои збирни податоци ќе им помогнат на апликациите и партнерите на Google, како што се програмерите на Android. Ако сте ја вклучиле дополнителната поставка „Активност на интернет и апликации“, овие податоци може да се зачувуваат во вашата сметка на Google. <ph name="BEGIN_LINK1" />Дознајте повеќе<ph name="END_LINK1" /></translation>
+<translation id="2944060181911631861">Испраќајте податоци за користење и дијагностика. Помогнете ни да го подобриме вашето доживување со Android со автоматско испраќање дијагностички и податоци за користењето на уредот и апликациите до Google. Овие податоци ќе ни помогнат околу стабилноста на системот и апликациите и за други подобрувања. Некои збирни податоци ќе им помогнат на апликациите и партнерите на Google, како што се програмерите на Android. Ако сте ја вклучиле дополнителната поставка „Активност на интернет и апликации“, овие податоци може да се зачувуваат во вашата сметка на Google. <ph name="BEGIN_LINK1" />Дознајте повеќе<ph name="END_LINK1" /></translation>
 <translation id="2946119680249604491">Додај врска</translation>
 <translation id="2947605845283690091">Прелистувањето на интернет треба да биде брзо. Одвојте малку време за да ги <ph name="BEGIN_LINK" />проверите екстензиите<ph name="END_LINK" /> сега.</translation>
 <translation id="2948300991547862301">Оди на <ph name="PAGE_TITLE" /></translation>
@@ -2442,7 +2442,7 @@
 <translation id="4209464433672152343">Документите се <ph name="BEGIN_LINK_HELP" />испраќаат до Google<ph name="END_LINK_HELP" /> за да се подготват за печатење. Прегледувајте ги, изменувајте ги и управувајте со своите печатачи и историјата на печатачите од <ph name="BEGIN_LINK_DASHBOARD" />контролната табла на Google Cloud Print<ph name="END_LINK_DASHBOARD" />.</translation>
 <translation id="4210048056321123003">Се презема виртуелната машина</translation>
 <translation id="421182450098841253">&amp;Покажи лента со обележувачи</translation>
-<translation id="4211851069413100178">Испраќајте податоци за користење и дијагностика. Помогнете ни да го подобриме вашето искуство со Android со автоматско испраќање дијагностички и податоци за користењето на уредот и апликациите до Google. Овие податоци ќе ни помогнат околу стабилноста на системот и апликациите и за други подобрувања. Некои збирни податоци ќе им помогнат на апликациите и партнерите на Google, како што се програмерите на Android. Оваа <ph name="BEGIN_LINK1" />поставка<ph name="END_LINK1" /> е наметната од сопственикот. Сопственикот може да избере да испраќа дијагностички и податоци за користењето на овој уред до Google. Ако сте ја вклучиле дополнителната поставка „Активност на интернет и апликации“, овие податоци може да се зачувуваат во вашата сметка на Google. <ph name="BEGIN_LINK2" />Дознајте повеќе<ph name="END_LINK2" /></translation>
+<translation id="4211851069413100178">Испраќајте податоци за користење и дијагностика. Помогнете ни да го подобриме вашето доживување со Android со автоматско испраќање дијагностички и податоци за користењето на уредот и апликациите до Google. Овие податоци ќе ни помогнат околу стабилноста на системот и апликациите и за други подобрувања. Некои збирни податоци ќе им помогнат на апликациите и партнерите на Google, како што се програмерите на Android. Оваа <ph name="BEGIN_LINK1" />поставка<ph name="END_LINK1" /> е наметната од сопственикот. Сопственикот може да избере да испраќа дијагностички и податоци за користењето на овој уред до Google. Ако сте ја вклучиле дополнителната поставка „Активност на интернет и апликации“, овие податоци може да се зачувуваат во вашата сметка на Google. <ph name="BEGIN_LINK2" />Дознајте повеќе<ph name="END_LINK2" /></translation>
 <translation id="42126664696688958">Извези</translation>
 <translation id="42137655013211669">Пристапот до изворов е забранет од серверот.</translation>
 <translation id="4218274196133425560">Отстранете го исклучокот за <ph name="HOST_NAME" /></translation>
@@ -5343,7 +5343,7 @@
 <translation id="8174047975335711832">Информации за уредот</translation>
 <translation id="8174876712881364124">Направете бекап на Google Drive. Лесно враќајте ги податоците или менувајте ги уредите во секое време. Бекапов опфаќа податоци за апликациите. Бекапот се прикачува во Google и се шифрира со помош на лозинката за сметката на Google на вашето дете. <ph name="BEGIN_LINK1" />Дознајте повеќе<ph name="END_LINK1" /></translation>
 <translation id="8176332201990304395">Розова и бела</translation>
-<translation id="8177196903785554304">Детали за мрежа</translation>
+<translation id="8177196903785554304">Детали за мрежата</translation>
 <translation id="8177318697334260664">{NUM_TABS,plural, =1{Преместете ја картичката во нов прозорец}one{Преместете ги картичките во нов прозорец}other{Преместете ги картичките во нов прозорец}}</translation>
 <translation id="8179976553408161302">Enter</translation>
 <translation id="8180239481735238521">страница</translation>
diff --git a/chrome/app/resources/generated_resources_mn.xtb b/chrome/app/resources/generated_resources_mn.xtb
index a766389..245733d 100644
--- a/chrome/app/resources/generated_resources_mn.xtb
+++ b/chrome/app/resources/generated_resources_mn.xtb
@@ -1475,7 +1475,7 @@
 <translation id="2948300991547862301"><ph name="PAGE_TITLE" /> руу очно уу</translation>
 <translation id="29488703364906173">Орчин үеийн вэб-д зориулан бүтээгдсэн хурдан, энгийн, аюулгүй вэб хөтөч.</translation>
 <translation id="2949289451367477459">Байршлыг ашиглана уу. Байршлын зөвшөөрөлтэй аппууд болон үйлчилгээнүүдэд энэ төхөөрөмжийн байршлыг ашиглахыг зөвшөөрнө үү. Google байршлын нарийвчлал болон байршилд суурилсан үйлчилгээнүүдийг сайжруулах зорилгоор байршлын өгөгдлийг үе үе цуглуулж, энэ өгөгдлийг үл мэдэгдэх байдлаар ашиглаж болзошгүй. <ph name="BEGIN_LINK1" />Нэмэлт мэдээлэл авах<ph name="END_LINK1" /></translation>
-<translation id="2950666755714083615">Намайг бүртгүүлэх</translation>
+<translation id="2950666755714083615">Намайг бүртгэнэ үү</translation>
 <translation id="2956070239128776395">Хэсэг нь бүлэг дотор байрлана: <ph name="ERROR_LINE" /></translation>
 <translation id="2957117904572187936">Ямар ч сайтад таны төхөөрөмжийн файл эсвэл фолдерыг засахыг битгий зөвшөөр</translation>
 <translation id="2958721676848865875">Өргөтгөлийг багцлах анхааруулга</translation>
diff --git a/chrome/app/resources/google_chrome_strings_bn.xtb b/chrome/app/resources/google_chrome_strings_bn.xtb
index 22a0f96..e48ce92 100644
--- a/chrome/app/resources/google_chrome_strings_bn.xtb
+++ b/chrome/app/resources/google_chrome_strings_bn.xtb
@@ -72,6 +72,7 @@
 <translation id="2929907241665500097">Chrome আপডেট করা যায়নি, কোনও সমস্যা হয়েছে। <ph name="BEGIN_LINK" />Chrome-এ আপডেট করতে না পারার সমস্যা ও আপডেট করা যায়নি এমন সমস্যার সমাধান করুন।<ph name="END_LINK" /></translation>
 <translation id="2969728957078202736"><ph name="PAGE_TITLE" /> - নেটওয়ার্ক সাইন-ইন - Chrome</translation>
 <translation id="3037838751736561277">Google Chrome পটভূমি মোডে রয়েছে।</translation>
+<translation id="3059710691562604940">'Safe Browsing'-এর সুবিধা বন্ধ করা আছে। তবে Chrome আপনাকে এটি চালু রাখার জন্য সাজেস্ট করছে।</translation>
 <translation id="3065168410429928842">Chrome ট্যাব</translation>
 <translation id="3080151273017101988">Google Chrome বন্ধ হলে পশ্চাদপট অ্যাপ্লিকেশানের চলা অবিরত রাখুন</translation>
 <translation id="3089968997497233615">Google Chrome-এর একটি নতুন, তুলনামূলক নিরাপদ ভার্সন উপলব্ধ৷</translation>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 83ead9c..07e77dac 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -66,27 +66,6 @@
   <message name="IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION_SUBTITLE" desc="Subtitle of the setting to enable Live Caption.">
     Live caption detects speech in media and automatically generates captions for all media playing in Chrome.
   </message>
-  <if expr="chromeos">
-    <!-- Android Apps Page -->
-    <message name="IDS_SETTINGS_ANDROID_APPS_TITLE" desc="The title of Google Play Store (Arc++ / Android Apps) section.">
-      Google Play Store
-    </message>
-    <message name="IDS_SETTINGS_ANDROID_SETTINGS_TITLE" desc="The title of Android settings section in case Play Store app is not available.">
-      Android settings
-    </message>
-    <message name="IDS_SETTINGS_ANDROID_APPS_SUBTEXT" desc="Description for the section for enabling and managing Google Play Store (Android) apps.">
-      Install apps and games from Google Play on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. &lt;a target="_blank" href="<ph name="URL">$2<ex>https://google.com/</ex></ph>"&gt;Learn more&lt;/a&gt;
-    </message>
-    <!-- TODO(jamescook): Use device type instead of "Chromebook", which may
-         require changing ArcPlayTermsOfServiceConsent resource id handling. -->
-    <message name="IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE" desc="Describes what will happen if the user opts out of android apps.">
-      Apps you’ve downloaded from Google Play will be deleted from this Chromebook.
-      <ph name="LINE_BREAKS1">&lt;br&gt;&lt;br&gt;</ph>
-      Content you’ve purchased such as movies, TV shows, music, books, or other in-app purchases may also be deleted.
-      <ph name="LINE_BREAKS2">&lt;br&gt;&lt;br&gt;</ph>
-      This doesn’t affect apps or content on other devices.
-    </message>
-  </if>
 
   <!-- Appearance Page -->
   <message name="IDS_SETTINGS_APPEARANCE" desc="Name of the settings page which displays appearance preferences.">
@@ -864,89 +843,6 @@
     Open certain file types automatically after downloading
   </message>
 
-  <!-- SMB File Shares -->
-  <if expr="chromeos">
-    <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_URL" desc="Title for the input that lets users specify the name of an SMB URL.">
-      File share URL
-    </message>
-    <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_NAME" desc="Title for the input that lets users specify the display name of an SMB mount.">
-      Display name (optional)
-    </message>
-    <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_USERNAME" desc="Title for the input that lets users specify their username for an SMB share.">
-      Username (optional)
-    </message>
-    <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_PASSWORD" desc="Title for the input that lets users specify their password for an SMB Share.">
-      Password (optional)
-    </message>
-    <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_SAVE_CREDENTIALS" desc="Label for the checkbox input that lets users have the username/password for an SMB share saved for the next login.">
-      Remember sign-in info
-    </message>
-    <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_AUTHENTICATION_METHOD" desc="Title for the input that lets users specify their authentication method for an SMB Share.">
-      Authentication method
-    </message>
-    <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_STANDARD_AUTHENTICATION" desc="Authentication method option indicating that fields for username and password should be shown to the user.">
-      Standard
-    </message>
-    <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_KERBEROS_AUTHENTICATION" desc="Authentication method option to use a users Kerberos ticket to authenticate. Only availible for Active Directory users.">
-      SSO
-    </message>
-    <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_DISCOVERY_MESSAGE" desc="The message shown next to the loading spinner shown when searching for SMB shares.">
-      Looking for file shares
-    </message>
-  </if>
-
-  <!-- Easy Unlock Page -->
-  <if expr="chromeos">
-    <message name="IDS_SETTINGS_EASY_UNLOCK_SETUP" desc="The label of the button to set up Easy Unlock section on the settings page.">
-      Set up
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_DESCRIPTION" desc="The text that describes what Easy Unlock does.">
-      Unlock your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> with your Android phone
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_TURN_OFF" desc="The label of the button to disable Easy unlock on the settings page and the turn off Easy unlock dialog.">
-      Turn off
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_TURN_OFF_TITLE" desc="The title of the Easy unlock turn off dialog.">
-      Turn off Smart Lock for <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>?
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_TURN_OFF_DESCRIPTION" desc="The description text of the Easy unlock turn off dialog.">
-      If you turn off Smart Lock for <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>, you won’t be able to unlock your Chrome devices using your phone. You'll need to type your password.
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_TURN_OFF_OFFLINE_TITLE" desc="The title text on the Easy unlock turn off dialog when Easy unlock could not be turned off because the device is offline.">
-      Please connect to a network
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_TURN_OFF_OFFLINE_MESSAGE" desc="The text on the Easy unlock turn off dialog when Easy unlock could not be turned off because the device is offline.">
-      You must be online to turn off Smart Lock because this setting is synced to your phone and other devices. Please connect to a network first.
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_TURN_OFF_ERROR_TITLE" desc="The title text on the Easy unlock turn off dialog when Easy unlock could not be turned off because there is a server error.">
-      Smart Lock is unavailable
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_TURN_OFF_ERROR_MESSAGE" desc="The text on the Easy unlock turn off dialog when Easy unlock could not be turned off because there is a server error.">
-      Smart Lock is currently unavailable. Please try again later.
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_ALLOW_SIGN_IN_LABEL" desc="The label text on the Easy unlock settings page for the radio box to allow the EasyUnlock on the sign-in screen (in addition to the lock screen).">
-      Use Smart Lock to sign in to your Google Account
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_PROXIMITY_THRESHOLD_LABEL" desc="The text on the Easy unlock settings page indicating how close the phone should be for unlock to work.">
-      Distance needed for phone to unlock this <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_PROXIMITY_THRESHOLD_VERY_CLOSE" desc="The text on the Easy unlock settings page indicating the phone should be very close for the unlock to work.">
-      Very close
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_PROXIMITY_THRESHOLD_CLOSE" desc="The text on the Easy unlock settings page indicating the phone should be close for the unlock to work." meaning="An adjective, not a verb, like 'nearby'.">
-      Close
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_PROXIMITY_THRESHOLD_FAR" desc="The text on the Easy unlock settings page indicating the phone can be far for the unlock to work.">
-      Far
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_PROXIMITY_THRESHOLD_VERY_FAR" desc="The text on the Easy unlock settings page indicating the phone can be very far for the unlock to work.">
-      Very far
-    </message>
-    <message name="IDS_SETTINGS_EASY_UNLOCK_OPTIONS" desc="Heading for options for the Smart Lock feature.">
-      Smart Lock options
-    </message>
-  </if>
-
   <!-- Strings specific to the Settings Internet Page -->
   <if expr="chromeos">
     <message name="IDS_SETTINGS_INTERNET_CONFIG" desc="Title for the network configuration dialog.">
@@ -1166,25 +1062,6 @@
     </message>
   </if>
 
-  <!-- Network error strings. -->
-  <if expr="chromeos">
-    <message name="IDS_NETWORK_ERROR_CANNOT_CHANGE_SHARED_CONFIG" desc="Network error message shown when attempting to change a shared network configuration if the operation is not allowed">
-      Changing shared network configurations is not allowed
-    </message>
-    <message name="IDS_NETWORK_ERROR_NO_USER_CERT" desc="In the network connect dialog, when creating a VPN or enterprise Wi-Fi connection, error message to display when no user certificates are installed.">
-      Please install a user certificate.
-    </message>
-    <message name="IDS_NETWORK_ERROR_POLICY_CONTROLLED" desc="Network error message shown when attempting to remove or illegally modify a policy controlled network">
-      Network is policy controlled
-    </message>
-    <message name="IDS_NETWORK_ERROR_PASSPHRASE_REQUIRED" desc="Network error message shown when a passphrase is required to connect to a network but was not supplied.">
-      Passphrase required
-    </message>
-    <message name="IDS_NETWORK_ERROR_UNKNOWN" desc="Network error message shown for an unknown or unexpected network configuration error">
-      Error configuring network
-    </message>
-  </if>
-
   <!-- On Startup Page -->
   <message name="IDS_SETTINGS_ON_STARTUP" desc="Name of the on startup page.">
     On startup
@@ -2794,19 +2671,6 @@
     </message>
   </if>
 
-  <!-- Add Supervision Dialog Strings -->
-  <if expr="chromeos">
-    <message name="IDS_SETTINGS_CLOSE_ADD_SUPERVISION_DIALOG_TITLE" desc="Title of dialog shown when a user closes the Add Supervision dialog after an account has been converted to use supervision.">
-      Sign out to finish?
-    </message>
-    <message name="IDS_SETTINGS_CLOSE_ADD_SUPERVISION_DIALOG_SIGN_OUT_BUTTON_LABEL" desc="Text of sign-out button on dialog shown when the Add Supervision flow is closed, which results in a user being signed out.">
-      Sign out
-    </message>
-    <message name="IDS_SETTINGS_CLOSE_ADD_SUPERVISION_DIALOG_CANCEL_BUTTON_LABEL" desc="Text of cancel button on dialog shown when the Add Supervision flow is closed, which results in a return to the Add Supervision flow.">
-      Cancel
-    </message>
-  </if>
-
   <!-- Web Content -->
   <message name="IDS_SETTINGS_PAGE_ZOOM_LABEL" desc="Label for the page zoom dropdown menu in settings.">
     Page zoom
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b4fe07b..25c70fc4 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -4849,6 +4849,10 @@
 #endif  // defined(OS_ANDROID)
 
 #if defined(OS_CHROMEOS)
+    {"launcher-settings-search", flag_descriptions::kLauncherSettingsSearchName,
+     flag_descriptions::kLauncherSettingsSearchDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(app_list_features::kLauncherSettingsSearch)},
+
     {"enable-suggested-files", flag_descriptions::kEnableSuggestedFilesName,
      flag_descriptions::kEnableSuggestedFilesDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(app_list_features::kEnableSuggestedFiles)},
@@ -5238,6 +5242,10 @@
      FEATURE_VALUE_TYPE(
          autofill::features::kAutofillEnableSurfacingServerCardNickname)},
 
+    {"app-cache", flag_descriptions::kAppCacheName,
+     flag_descriptions::kAppCacheDescription, kOsAll,
+     FEATURE_VALUE_TYPE(blink::features::kAppCache)},
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/favicon_helper.cc b/chrome/browser/android/favicon_helper.cc
index a2e4a8aa..29dfac4 100644
--- a/chrome/browser/android/favicon_helper.cc
+++ b/chrome/browser/android/favicon_helper.cc
@@ -44,6 +44,7 @@
 using base::android::ConvertJavaStringToUTF16;
 using base::android::ConvertJavaStringToUTF8;
 using base::android::ConvertUTF8ToJavaString;
+using JobFinishedCallback = base::OnceCallback<void(void)>;
 
 namespace {
 
@@ -61,7 +62,102 @@
   return reinterpret_cast<intptr_t>(new FaviconHelper());
 }
 
-FaviconHelper::FaviconHelper() {
+// This is used by the FaviconHelper::GetComposedFaviconImageInternal, and it is
+// used to manage multiple FaviconService::GetRawFaviconForPageURL calls. The
+// number of calls is the size of the urls_. The Job is destroyed after the
+// number of calls have been reached, and the result_callback_ is finished.
+class FaviconHelper::Job {
+ public:
+  Job(FaviconHelper* favicon_helper,
+      favicon::FaviconService* favicon_service,
+      std::vector<std::string> urls,
+      int desire_size_in_pixel,
+      JobFinishedCallback job_finished_callback,
+      favicon_base::FaviconResultsCallback result_callback);
+
+  Job(const Job&) = delete;
+  Job& operator=(const Job&) = delete;
+
+  void Start();
+
+ private:
+  void OnFaviconAvailable(int favicon_index,
+                          const favicon_base::FaviconRawBitmapResult& result);
+  FaviconHelper* favicon_helper_;
+  favicon::FaviconService* favicon_service_;
+  std::vector<std::string> urls_;
+  int desire_size_in_pixel_;
+  JobFinishedCallback job_finished_callback_;
+  favicon_base::FaviconResultsCallback result_callback_;
+  int favicon_expected_count_;
+  std::vector<favicon_base::FaviconRawBitmapResult> favicon_raw_bitmap_results_;
+  int favicon_result_count_;
+
+  base::WeakPtrFactory<Job> weak_ptr_factory_{this};
+};
+
+FaviconHelper::Job::Job(FaviconHelper* favicon_helper,
+                        favicon::FaviconService* favicon_service,
+                        std::vector<std::string> urls,
+                        int desire_size_in_pixel,
+                        JobFinishedCallback job_finished_callback,
+                        favicon_base::FaviconResultsCallback result_callback)
+    : favicon_helper_(favicon_helper),
+      favicon_service_(favicon_service),
+      urls_(urls),
+      desire_size_in_pixel_(desire_size_in_pixel),
+      job_finished_callback_(std::move(job_finished_callback)),
+      result_callback_(std::move(result_callback)),
+      favicon_raw_bitmap_results_(4),
+      favicon_result_count_(0) {
+  favicon_expected_count_ = urls_.size();
+}
+
+void FaviconHelper::Job::Start() {
+  size_t urls_size = urls_.size();
+  DCHECK(urls_size > 1 && urls_size <= 4);
+  if (urls_size <= 1 || urls_size > 4)
+    return;
+
+  for (size_t i = 0; i < urls_size; i++) {
+    favicon_base::FaviconRawBitmapCallback callback =
+        base::BindOnce(&FaviconHelper::Job::OnFaviconAvailable,
+                       weak_ptr_factory_.GetWeakPtr(), i);
+
+    favicon_helper_->GetLocalFaviconImageForURLInternal(
+        favicon_service_, GURL(urls_.at(i)), desire_size_in_pixel_,
+        std::move(callback));
+  }
+}
+
+void FaviconHelper::Job::OnFaviconAvailable(
+    int favicon_index,
+    const favicon_base::FaviconRawBitmapResult& result) {
+  DCHECK(favicon_index >= 0 && favicon_index < 4);
+
+  if (result.is_valid()) {
+    favicon_raw_bitmap_results_.at(favicon_index) = result;
+    favicon_result_count_++;
+  } else {
+    favicon_expected_count_--;
+  }
+
+  if (favicon_result_count_ == favicon_expected_count_) {
+    size_t i = 0;
+    while (i < favicon_raw_bitmap_results_.size()) {
+      if (!favicon_raw_bitmap_results_[i].is_valid()) {
+        favicon_raw_bitmap_results_.erase(favicon_raw_bitmap_results_.begin() +
+                                          i);
+        continue;
+      }
+      i++;
+    }
+    std::move(result_callback_).Run(favicon_raw_bitmap_results_);
+    std::move(job_finished_callback_).Run();
+  }
+}
+
+FaviconHelper::FaviconHelper() : last_used_job_id_(0) {
   cancelable_task_tracker_.reset(new base::CancelableTaskTracker());
 }
 
@@ -75,14 +171,59 @@
     const base::android::JavaParamRef<jobjectArray>& j_urls,
     jint j_desired_size_in_pixel,
     const base::android::JavaParamRef<jobject>& j_favicon_image_callback) {
-  // TODO(crbug.com/1064153): Real implementation.
-  ScopedJavaLocalRef<jobject> j_favicon_bitmap;
-  ScopedJavaLocalRef<jstring> j_icon_url;
-  Java_FaviconImageCallback_onFaviconAvailable(env, j_favicon_image_callback,
-                                               j_favicon_bitmap, j_icon_url);
+  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
+  DCHECK(profile);
+  if (!profile)
+    return false;
+
+  favicon::FaviconService* favicon_service =
+      FaviconServiceFactory::GetForProfile(profile,
+                                           ServiceAccessType::EXPLICIT_ACCESS);
+
+  DCHECK(favicon_service);
+  if (!favicon_service)
+    return false;
+
+  favicon_base::FaviconResultsCallback callback_runner =
+      base::BindOnce(&FaviconHelper::OnFaviconBitmapResultsAvailable,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     ScopedJavaGlobalRef<jobject>(j_favicon_image_callback));
+
+  std::vector<std::string> urls;
+  base::android::AppendJavaStringArrayToStringVector(env, j_urls, &urls);
+
+  GetComposedFaviconImageInternal(favicon_service, urls,
+                                  static_cast<int>(j_desired_size_in_pixel),
+                                  std::move(callback_runner));
+
   return true;
 }
 
+void FaviconHelper::GetComposedFaviconImageInternal(
+    favicon::FaviconService* favicon_service,
+    std::vector<std::string> urls,
+    int desired_size_in_pixel,
+    favicon_base::FaviconResultsCallback callback_runner) {
+  DCHECK(favicon_service);
+
+  JobFinishedCallback job_finished_callback =
+      base::BindOnce(&FaviconHelper::OnJobFinished,
+                     weak_ptr_factory_.GetWeakPtr(), ++last_used_job_id_);
+
+  auto job = std::make_unique<Job>(
+      this, favicon_service, urls, desired_size_in_pixel,
+      std::move(job_finished_callback), std::move(callback_runner));
+
+  id_to_job_[last_used_job_id_] = std::move(job);
+  id_to_job_[last_used_job_id_]->Start();
+}
+
+void ::FaviconHelper::OnJobFinished(int job_id) {
+  DCHECK(id_to_job_.count(job_id));
+
+  id_to_job_.erase(job_id);
+}
+
 jboolean FaviconHelper::GetLocalFaviconImageForURL(
     JNIEnv* env,
     const JavaParamRef<jobject>& j_profile,
@@ -106,6 +247,22 @@
                      weak_ptr_factory_.GetWeakPtr(),
                      ScopedJavaGlobalRef<jobject>(j_favicon_image_callback));
 
+  GetLocalFaviconImageForURLInternal(
+      favicon_service, GURL(ConvertJavaStringToUTF16(env, j_page_url)),
+      static_cast<int>(j_desired_size_in_pixel), std::move(callback_runner));
+
+  return true;
+}
+
+void FaviconHelper::GetLocalFaviconImageForURLInternal(
+    favicon::FaviconService* favicon_service,
+    GURL url,
+    int desired_size_in_pixel,
+    favicon_base::FaviconRawBitmapCallback callback_runner) {
+  DCHECK(favicon_service);
+  if (!favicon_service)
+    return;
+
   // |j_page_url| is an origin, and it may not have had a favicon associated
   // with it. A trickier case is when |j_page_url| only has domain-scoped
   // cookies, but visitors are redirected to HTTPS on visiting. Then
@@ -115,14 +272,12 @@
   // to matching only the hostname to have the best chance of finding a favicon.
   const bool fallback_to_host = true;
   favicon_service->GetRawFaviconForPageURL(
-      GURL(ConvertJavaStringToUTF16(env, j_page_url)),
+      url,
       {favicon_base::IconType::kFavicon, favicon_base::IconType::kTouchIcon,
        favicon_base::IconType::kTouchPrecomposedIcon,
        favicon_base::IconType::kWebManifestIcon},
-      static_cast<int>(j_desired_size_in_pixel), fallback_to_host,
-      std::move(callback_runner), cancelable_task_tracker_.get());
-
-  return true;
+      desired_size_in_pixel, fallback_to_host, std::move(callback_runner),
+      cancelable_task_tracker_.get());
 }
 
 jboolean FaviconHelper::GetForeignFaviconImageForURL(
@@ -304,3 +459,17 @@
   Java_FaviconImageCallback_onFaviconAvailable(env, j_favicon_image_callback,
                                                j_favicon_bitmap, j_icon_url);
 }
+
+void FaviconHelper::OnFaviconBitmapResultsAvailable(
+    const JavaRef<jobject>& j_favicon_image_callback,
+    const std::vector<favicon_base::FaviconRawBitmapResult>& results) {
+  JNIEnv* env = AttachCurrentThread();
+  // TODO(crbug.com/1064153): Integrate with ImageHelper to compose favicons.
+  // Convert favicon_image_result to java objects.
+  ScopedJavaLocalRef<jstring> j_icon_url;
+  ScopedJavaLocalRef<jobject> j_favicon_bitmap;
+
+  // Call java side OnFaviconBitmapResultAvailable method.
+  Java_FaviconImageCallback_onFaviconAvailable(env, j_favicon_image_callback,
+                                               j_favicon_bitmap, j_icon_url);
+}
diff --git a/chrome/browser/android/favicon_helper.h b/chrome/browser/android/favicon_helper.h
index 3e45ad38..25e30c9 100644
--- a/chrome/browser/android/favicon_helper.h
+++ b/chrome/browser/android/favicon_helper.h
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/task/cancelable_task_tracker.h"
+#include "components/favicon/core/favicon_service.h"
 #include "components/favicon_base/favicon_types.h"
 #include "url/gurl.h"
 
@@ -58,12 +59,25 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& j_profile,
       const base::android::JavaParamRef<jstring>& j_icon_url);
+  void GetLocalFaviconImageForURLInternal(
+      favicon::FaviconService* favicon_service,
+      GURL url,
+      int desired_size_in_pixel,
+      favicon_base::FaviconRawBitmapCallback callback_runner);
+  void GetComposedFaviconImageInternal(
+      favicon::FaviconService* favicon_service,
+      std::vector<std::string> urls,
+      int desired_size_in_pixel,
+      favicon_base::FaviconResultsCallback callback_runner);
+  void OnJobFinished(int job_id);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(FaviconHelperTest, GetLargestSizeIndex);
 
   virtual ~FaviconHelper();
 
+  class Job;
+
   static void OnFaviconImageResultAvailable(
       const base::android::ScopedJavaGlobalRef<jobject>&
           j_availability_callback,
@@ -95,8 +109,15 @@
       const base::android::JavaRef<jobject>& j_favicon_image_callback,
       const favicon_base::FaviconRawBitmapResult& result);
 
+  void OnFaviconBitmapResultsAvailable(
+      const base::android::JavaRef<jobject>& j_favicon_image_callback,
+      const std::vector<favicon_base::FaviconRawBitmapResult>& result);
+
   std::unique_ptr<base::CancelableTaskTracker> cancelable_task_tracker_;
 
+  std::map<int, std::unique_ptr<Job>> id_to_job_;
+  int last_used_job_id_;
+
   base::WeakPtrFactory<FaviconHelper> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(FaviconHelper);
diff --git a/chrome/browser/android/favicon_helper_unittest.cc b/chrome/browser/android/favicon_helper_unittest.cc
index 8b7d0be..e86be60 100644
--- a/chrome/browser/android/favicon_helper_unittest.cc
+++ b/chrome/browser/android/favicon_helper_unittest.cc
@@ -4,9 +4,75 @@
 
 #include "chrome/browser/android/favicon_helper.h"
 
-#include "testing/gtest/include/gtest/gtest.h"
+#include <vector>
 
-TEST(FaviconHelperTest, GetLargestSizeIndex) {
+#include "base/test/task_environment.h"
+#include "components/favicon/core/test/mock_favicon_service.h"
+#include "components/favicon_base/favicon_callback.h"
+#include "components/favicon_base/favicon_types.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "url/gurl.h"
+
+using ::testing::_;
+const int kDummyTaskId = 1;
+
+favicon_base::FaviconRawBitmapResult
+CreateTestBitmapResult(GURL url, int size, SkColor color = SK_ColorRED) {
+  favicon_base::FaviconRawBitmapResult result;
+  result.expired = false;
+
+  // Create bitmap and fill with |color|.
+  scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
+  SkBitmap bitmap;
+  bitmap.allocN32Pixels(size, size);
+  bitmap.eraseColor(color);
+  gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &data->data());
+
+  result.bitmap_data = data;
+  result.pixel_size = gfx::Size(size, size);
+  result.icon_url = url;
+  result.icon_type = favicon_base::IconType::kFavicon;
+  CHECK(result.is_valid());
+  return result;
+}
+
+class FaviconHelperTest : public testing::Test {
+ public:
+  FaviconHelperTest() {
+    ON_CALL(mock_favicon_service_, GetRawFaviconForPageURL(_, _, _, _, _, _))
+        .WillByDefault([](const GURL& url, auto, int size, auto,
+                          favicon_base::FaviconRawBitmapCallback callback,
+                          auto) {
+          std::move(callback).Run(CreateTestBitmapResult(url, size));
+          return kDummyTaskId;
+        });
+
+    get_composed_favicon_raw_results_callback_ = base::BindOnce(
+        &FaviconHelperTest::onNativeGetComposedFaviconImageFinished,
+        base::Unretained(this));
+  }
+
+  ~FaviconHelperTest() override { favicon_helper_->Destroy(nullptr); }
+
+  void onNativeGetComposedFaviconImageFinished(
+      const std::vector<favicon_base::FaviconRawBitmapResult>& result) {
+    raw_bitmap_results_ = result;
+  }
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
+  favicon::MockFaviconService mock_favicon_service_;
+  FaviconHelper* favicon_helper_ = new FaviconHelper();
+  std::vector<favicon_base::FaviconRawBitmapResult> raw_bitmap_results_;
+  favicon_base::FaviconResultsCallback
+      get_composed_favicon_raw_results_callback_;
+};
+
+TEST_F(FaviconHelperTest, GetLargestSizeIndex) {
   std::vector<gfx::Size> sizes;
   gfx::Size size1 = gfx::Size(INT_MAX, INT_MAX);
   sizes.push_back(size1);
@@ -20,3 +86,103 @@
   sizes.push_back(size1);
   EXPECT_EQ(0u, FaviconHelper::GetLargestSizeIndex(sizes));
 }
+
+TEST_F(FaviconHelperTest, GetComposedFaviconImage) {
+  raw_bitmap_results_.clear();
+  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, _, _))
+      .Times(1);
+  EXPECT_CALL(mock_favicon_service_,
+              GetRawFaviconForPageURL(url2, _, _, 16, _, _))
+      .Times(1);
+
+  favicon_helper_->GetComposedFaviconImageInternal(
+      &mock_favicon_service_, urls, 16,
+      std::move(get_composed_favicon_raw_results_callback_));
+
+  task_environment_.RunUntilIdle();
+
+  EXPECT_EQ(2, (int)raw_bitmap_results_.size());
+}
+
+TEST_F(FaviconHelperTest, GetComposedFaviconImageWithOneFaviconFailed) {
+  raw_bitmap_results_.clear();
+  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, _, _))
+      .Times(1);
+  EXPECT_CALL(mock_favicon_service_,
+              GetRawFaviconForPageURL(url2, _, _, 16, _, _))
+      .Times(1);
+  // With one favicon failed.
+  EXPECT_CALL(mock_favicon_service_,
+              GetRawFaviconForPageURL(url3, _, _, 16, _, _))
+      .WillOnce([](auto, auto, auto, auto,
+                   favicon_base::FaviconRawBitmapCallback callback, auto) {
+        std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
+        return kDummyTaskId;
+      });
+
+  favicon_helper_->GetComposedFaviconImageInternal(
+      &mock_favicon_service_, urls, 16,
+      std::move(get_composed_favicon_raw_results_callback_));
+
+  task_environment_.RunUntilIdle();
+
+  EXPECT_EQ(2, (int)raw_bitmap_results_.size());
+}
+
+TEST_F(FaviconHelperTest, GetComposedFaviconImageOrderMatchesInput) {
+  raw_bitmap_results_.clear();
+  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, _, _))
+      .Times(1);
+
+  EXPECT_CALL(mock_favicon_service_,
+              GetRawFaviconForPageURL(url2, _, _, 16, _, _))
+      .WillOnce([](const GURL& url, auto, int size, auto,
+                   favicon_base::FaviconRawBitmapCallback callback,
+                   base::CancelableTaskTracker* tracker) {
+        tracker->PostTask(
+            base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE,
+            base::BindOnce(
+                [](favicon_base::FaviconRawBitmapCallback callback, GURL url,
+                   int size) {
+                  sleep(5);
+                  std::move(callback).Run(CreateTestBitmapResult(url, size));
+                },
+                std::move(callback), url, size));
+        return kDummyTaskId;
+      });
+
+  EXPECT_CALL(mock_favicon_service_,
+              GetRawFaviconForPageURL(url3, _, _, 16, _, _))
+      .Times(1);
+
+  favicon_helper_->GetComposedFaviconImageInternal(
+      &mock_favicon_service_, urls, 16,
+      std::move(get_composed_favicon_raw_results_callback_));
+
+  task_environment_.RunUntilIdle();
+
+  EXPECT_EQ(3, (int)raw_bitmap_results_.size());
+  EXPECT_EQ(url1, raw_bitmap_results_[0].icon_url);
+  EXPECT_EQ(url2, raw_bitmap_results_[1].icon_url);
+  EXPECT_EQ(url3, raw_bitmap_results_[2].icon_url);
+}
diff --git a/chrome/browser/android/feed/v2/feed_stream_surface.cc b/chrome/browser/android/feed/v2/feed_stream_surface.cc
index 96c77d0d..f92e7e9 100644
--- a/chrome/browser/android/feed/v2/feed_stream_surface.cc
+++ b/chrome/browser/android/feed/v2/feed_stream_surface.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/android/feed/v2/feed_stream_surface.h"
 
+#include <vector>
+
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
 #include "chrome/android/chrome_jni_headers/FeedStreamSurface_jni.h"
@@ -93,37 +95,44 @@
     const JavaParamRef<jobject>& obj,
     const JavaParamRef<jstring>& url,
     jboolean in_new_tab) {
-  // TODO(harringtond): Implement this.
+  feed_stream_api_->ReportNavigationStarted();
 }
 
 void FeedStreamSurface::ReportNavigationDone(JNIEnv* env,
                                              const JavaParamRef<jobject>& obj,
                                              const JavaParamRef<jstring>& url,
                                              jboolean in_new_tab) {
-  // TODO(harringtond): Implement this.
+  feed_stream_api_->ReportNavigationDone();
 }
 
 void FeedStreamSurface::ReportContentRemoved(JNIEnv* env,
                                              const JavaParamRef<jobject>& obj) {
-  // TODO(harringtond): Implement this.
+  feed_stream_api_->ReportContentRemoved();
 }
 
 void FeedStreamSurface::ReportNotInterestedIn(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
-  // TODO(harringtond): Implement this.
+  feed_stream_api_->ReportNotInterestedIn();
 }
 
 void FeedStreamSurface::ReportManageInterests(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
-  // TODO(harringtond): Implement this.
+  feed_stream_api_->ReportManageInterests();
 }
 
 void FeedStreamSurface::ReportContextMenuOpened(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
-  // TODO(harringtond): Implement this.
+  feed_stream_api_->ReportContextMenuOpened();
+}
+
+void FeedStreamSurface::ReportStreamScrolled(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj,
+    int distance_dp) {
+  feed_stream_api_->ReportStreamScrolled(distance_dp);
 }
 
 }  // namespace feed
diff --git a/chrome/browser/android/feed/v2/feed_stream_surface.h b/chrome/browser/android/feed/v2/feed_stream_surface.h
index fb5918a91..a3bf961 100644
--- a/chrome/browser/android/feed/v2/feed_stream_surface.h
+++ b/chrome/browser/android/feed/v2/feed_stream_surface.h
@@ -85,6 +85,11 @@
   void ReportContextMenuOpened(JNIEnv* env,
                                const base::android::JavaParamRef<jobject>& obj);
 
+  // The user scrolled the feed by |distance_dp| and then stopped.
+  void ReportStreamScrolled(JNIEnv* env,
+                            const base::android::JavaParamRef<jobject>& obj,
+                            int distance_dp);
+
  private:
   base::android::ScopedJavaGlobalRef<jobject> java_ref_;
   FeedStreamApi* feed_stream_api_;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 2668821..6c80856 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -3167,6 +3167,7 @@
     "system/device_disabling_manager_unittest.cc",
     "system/procfs_util_unittest.cc",
     "system/user_removal_manager_unittest.cc",
+    "system_logs/debug_daemon_log_source_unittest.cc",
     "system_logs/single_debug_daemon_log_source_unittest.cc",
     "system_logs/single_log_file_log_source_unittest.cc",
     "tether/tether_service_unittest.cc",
diff --git a/chrome/browser/chromeos/crostini/crostini_terminal.cc b/chrome/browser/chromeos/crostini/crostini_terminal.cc
index f8e60f6b..a001072 100644
--- a/chrome/browser/chromeos/crostini/crostini_terminal.cc
+++ b/chrome/browser/chromeos/crostini/crostini_terminal.cc
@@ -36,7 +36,7 @@
 
 constexpr char kSettingBackgroundColor[] =
     "/hterm/profiles/default/background-color";
-constexpr char kDefaultBackgroundColor[] = "#101010";
+constexpr char kDefaultBackgroundColor[] = "#202124";
 
 constexpr char kSettingPassCtrlW[] = "/hterm/profiles/default/pass-ctrl-w";
 constexpr bool kDefaultPassCtrlW = false;
diff --git a/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher_impl_unittest.cc b/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher_impl_unittest.cc
index 3efd876..40ca131 100644
--- a/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher_impl_unittest.cc
+++ b/chrome/browser/chromeos/login/screens/recommend_apps/recommend_apps_fetcher_impl_unittest.cc
@@ -110,6 +110,7 @@
                         ash::mojom::DisplayConfigOperation op,
                         ash::mojom::TouchCalibrationPtr calibration,
                         TouchCalibrationCallback callback) override {}
+  void HighlightDisplay(int64_t id) override {}
 
  private:
   mojo::Receiver<ash::mojom::CrosDisplayConfigController> receiver_;
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
index 92f35ec..3936c1f 100644
--- a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
@@ -32,6 +32,7 @@
 constexpr char kNotAvailable[] = "<not available>";
 constexpr char kRoutesKeyName[] = "routes";
 constexpr char kNetworkStatusKeyName[] = "network-status";
+constexpr char kLogTruncated[] = "<earlier logs truncated>\n";
 
 // List of user log files that Chrome reads directly as these logs are generated
 // by Chrome itself.
@@ -49,6 +50,68 @@
     {"logout-times", "logout-times"},
 };
 
+// Buffer size for user logs in bytes. Given that maximum feedback report size
+// is ~7M and that majority of log files are under 1M, we set a per-file limit
+// of 1MiB.
+const int64_t kMaxLogSize = 1024 * 1024;
+
+}  // namespace
+
+bool ReadEndOfFile(const base::FilePath& path,
+                   std::string* contents,
+                   size_t max_size) {
+  if (!contents) {
+    LOG(ERROR) << "contents buffer is null.";
+    return false;
+  }
+
+  if (path.ReferencesParent()) {
+    LOG(ERROR) << "ReadEndOfFile can't be called on file paths with parent "
+                  "references.";
+    return false;
+  }
+
+  base::ScopedFILE fp(base::OpenFile(path, "r"));
+  if (!fp) {
+    PLOG(ERROR) << "Failed to open file " << path.value();
+    return false;
+  }
+
+  std::unique_ptr<char[]> chunk(new char[max_size]);
+  std::unique_ptr<char[]> last_chunk(new char[max_size]);
+  chunk[0] = '\0';
+  last_chunk[0] = '\0';
+
+  size_t bytes_read = 0;
+
+  // Since most logs are not seekable, read until the end keeping tracking of
+  // last two chunks.
+  while ((bytes_read = fread(chunk.get(), 1, max_size, fp.get())) == max_size) {
+    last_chunk.swap(chunk);
+    chunk[0] = '\0';
+  }
+
+  if (last_chunk[0] == '\0') {
+    // File is smaller than max_size
+    contents->assign(chunk.get(), bytes_read);
+  } else if (bytes_read == 0) {
+    // File is exactly max_size or a multiple of max_size
+    contents->assign(last_chunk.get(), max_size);
+  } else {
+    // Number of bytes to keep from last_chunk
+    size_t bytes_from_last = max_size - bytes_read;
+
+    // Shift left last_chunk by size of chunk and fit it in the back of
+    // last_chunk.
+    memmove(last_chunk.get(), last_chunk.get() + bytes_read, bytes_from_last);
+    memcpy(last_chunk.get() + bytes_from_last, chunk.get(), bytes_read);
+
+    contents->assign(last_chunk.get(), max_size);
+  }
+
+  return true;
+}
+
 // Reads the contents of the user log files listed in |kUserLogs| and adds them
 // to the |response| parameter.
 void ReadUserLogFiles(const std::vector<base::FilePath>& profile_dirs,
@@ -57,8 +120,16 @@
     std::string profile_prefix = "Profile[" + base::NumberToString(i) + "] ";
     for (const auto& log : kUserLogs) {
       std::string value;
-      const bool read_success = base::ReadFileToString(
-          profile_dirs[i].Append(log.log_file_relative_path), &value);
+      const bool read_success =
+          ReadEndOfFile(profile_dirs[i].Append(log.log_file_relative_path),
+                        &value, kMaxLogSize);
+
+      if (read_success && value.length() == kMaxLogSize) {
+        value.replace(0, strlen(kLogTruncated), kLogTruncated);
+
+        LOG(WARNING) << "Large log file was likely truncated: "
+                     << log.log_file_relative_path;
+      }
 
       response->emplace(
           profile_prefix + log.log_key,
@@ -67,8 +138,6 @@
   }
 }
 
-}  // namespace
-
 DebugDaemonLogSource::DebugDaemonLogSource(bool scrub)
     : SystemLogsSource("DebugDemon"),
       response_(new SystemLogsResponse()),
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
index 008fc04..b4229833 100644
--- a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
+++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
@@ -18,6 +18,15 @@
 
 namespace system_logs {
 
+// Reads the file at |path| into |contents| and returns true on success and
+// false on error. For security reasons a |path| containing path traversal
+// components ('..') is treated as a read error and |contents| is not changed.
+// When the file exceeds |max_size| function returns true with the last
+// |max_size| bytes from the file.
+bool ReadEndOfFile(const base::FilePath& path,
+                   std::string* contents,
+                   size_t max_size);
+
 // Gathers log data from Debug Daemon.
 class DebugDaemonLogSource : public SystemLogsSource {
  public:
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source_unittest.cc b/chrome/browser/chromeos/system_logs/debug_daemon_log_source_unittest.cc
new file mode 100644
index 0000000..2116b9c
--- /dev/null
+++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source_unittest.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/system_logs/debug_daemon_log_source.h"
+
+#include <string>
+
+#include "base/files/file_util.h"
+#include "base/files/scoped_file.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/rand_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace system_logs {
+
+class DebugDaemonLogSourceTest : public ::testing::Test {
+ public:
+  void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
+
+  base::ScopedTempDir temp_dir_;
+};
+
+TEST_F(DebugDaemonLogSourceTest, ReadEndOfFileEmpty) {
+  std::string read_data("should be erased");
+
+  base::FilePath file_path = temp_dir_.GetPath().Append("test_empty.txt");
+
+  WriteFile(file_path, "", 0);
+
+  EXPECT_TRUE(ReadEndOfFile(file_path, &read_data, 10));
+  EXPECT_EQ(0u, read_data.length());
+}
+
+TEST_F(DebugDaemonLogSourceTest, ReadEndOfFileSmall) {
+  const char kTestData[] = "0123456789";  // Length of 10
+  std::string read_data;
+
+  base::FilePath file_path = temp_dir_.GetPath().Append("test.txt");
+
+  WriteFile(file_path, kTestData, strlen(kTestData));
+
+  read_data.clear();
+  EXPECT_TRUE(ReadEndOfFile(file_path, &read_data, 15));
+  EXPECT_EQ(kTestData, read_data);
+
+  read_data.clear();
+  EXPECT_TRUE(ReadEndOfFile(file_path, &read_data, 10));
+  EXPECT_EQ(kTestData, read_data);
+
+  read_data.clear();
+  EXPECT_TRUE(ReadEndOfFile(file_path, &read_data, 2));
+  EXPECT_EQ("89", read_data);
+
+  read_data.clear();
+  EXPECT_TRUE(ReadEndOfFile(file_path, &read_data, 3));
+  EXPECT_EQ("789", read_data);
+
+  read_data.clear();
+  EXPECT_TRUE(ReadEndOfFile(file_path, &read_data, 5));
+  EXPECT_EQ("56789", read_data);
+}
+
+TEST_F(DebugDaemonLogSourceTest, ReadEndOfFileMedium) {
+  std::string test_data = base::RandBytesAsString(10000);  // 10KB data
+  std::string read_data;
+
+  const size_t test_size = test_data.length();
+
+  base::FilePath file_path = temp_dir_.GetPath().Append("test_med.txt");
+
+  WriteFile(file_path, test_data.data(), test_size);
+
+  read_data.clear();
+  EXPECT_TRUE(ReadEndOfFile(file_path, &read_data, 15000));
+  EXPECT_EQ(test_data, read_data);
+
+  read_data.clear();
+  EXPECT_TRUE(ReadEndOfFile(file_path, &read_data, 10000));
+  EXPECT_EQ(test_data, read_data);
+
+  read_data.clear();
+  EXPECT_TRUE(ReadEndOfFile(file_path, &read_data, 1000));
+  EXPECT_EQ(test_data.substr(test_size - 1000, 1000), read_data);
+
+  read_data.clear();
+  EXPECT_TRUE(ReadEndOfFile(file_path, &read_data, 300));
+  EXPECT_EQ(test_data.substr(test_size - 300, 300), read_data);
+
+  read_data.clear();
+  EXPECT_TRUE(ReadEndOfFile(file_path, &read_data, 175));
+  EXPECT_EQ(test_data.substr(test_size - 175, 175), read_data);
+}
+
+}  // namespace system_logs
diff --git a/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc
index c054ff4..6399ad9 100644
--- a/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc
@@ -55,7 +55,7 @@
 
     // Create extension directory.
     ASSERT_TRUE(base::CreateDirectory(extension_dir));
-    TestRulesetInfo info = {kJSONRulesFilename, base::ListValue()};
+    TestRulesetInfo info(kJSONRulesFilename, base::ListValue());
     WriteManifestAndRuleset(
         extension_dir, info,
         std::vector<std::string>({URLPattern::kAllUrlsPattern}), flags);
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
index 45a13ce..4e9a4cb 100644
--- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -420,9 +420,9 @@
   void LoadExtensionWithRules(const std::vector<TestRule>& rules,
                               const std::string& directory,
                               const std::vector<std::string>& hosts) {
-    std::vector<TestRulesetInfo> rulesets;
-    rulesets.push_back({kJSONRulesFilename, std::move(*ToListValue(rules))});
-    LoadExtensionWithRulesets(rulesets, directory, hosts, rules.size());
+    LoadExtensionWithRulesets(
+        {TestRulesetInfo(kJSONRulesFilename, *ToListValue(rules))}, directory,
+        hosts, rules.size());
   }
 
   // Returns a url with |filter| as a substring.
@@ -1716,10 +1716,7 @@
 
     expected_blocked_urls.push_back(GetURLForFilter(id));
 
-    TestRulesetInfo info;
-    info.relative_file_path = id;
-    info.rules_value = std::move(*ToListValue(rules));
-    rulesets.push_back(std::move(info));
+    rulesets.emplace_back(id, *ToListValue(rules));
   }
 
   // Set-up an observer for RulesetMatcher to monitor the number of extension
@@ -2166,10 +2163,7 @@
 
     urls_for_indices.push_back(GetURLForFilter(id));
 
-    TestRulesetInfo info;
-    info.relative_file_path = id;
-    info.rules_value = std::move(*ToListValue(rules));
-    rulesets.push_back(std::move(info));
+    rulesets.emplace_back(id, *ToListValue(rules));
   }
 
   // Set-up an observer for RulesetMatcher to monitor the number of extension
@@ -2182,7 +2176,6 @@
   ruleset_count_waiter.WaitForRulesetCount(1);
 
   const ExtensionId extension_id = last_loaded_extension_id();
-
   EXPECT_TRUE(ruleset_manager()->GetMatcherForExtension(extension_id));
 
   const Extension* extension = extension_registry()->GetExtensionById(
@@ -2268,12 +2261,8 @@
 
   const int kNumStaticRulesets = 4;
   std::vector<TestRulesetInfo> rulesets;
-  for (int i = 0; i < kNumStaticRulesets; ++i) {
-    TestRulesetInfo info;
-    info.relative_file_path = base::NumberToString(i);
-    info.rules_value = std::move(*ToListValue({rule}));
-    rulesets.push_back(std::move(info));
-  }
+  for (int i = 0; i < kNumStaticRulesets; ++i)
+    rulesets.emplace_back(base::NumberToString(i), *ToListValue({rule}));
 
   ASSERT_NO_FATAL_FAILURE(
       LoadExtensionWithRulesets(rulesets, "extension_directory", {} /* hosts */,
diff --git a/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc
index b32e3bd..337f5e39 100644
--- a/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc
@@ -195,8 +195,9 @@
     if (!rules_value_)
       rules_value_ = ToListValue(rules_list_);
 
-    TestRulesetInfo info = {kJSONRulesFilename, std::move(*rules_value_)};
-    WriteManifestAndRuleset(extension_dir(), info, {} /* hosts */);
+    WriteManifestAndRuleset(extension_dir(),
+                            TestRulesetInfo(kJSONRulesFilename, *rules_value_),
+                            {} /* hosts */);
 
     // Overwrite the JSON rules file with some invalid json.
     if (persist_invalid_json_file_) {
@@ -670,9 +671,7 @@
     WriteManifestAndRulesets(extension_dir(), rulesets_, {} /* hosts */);
   }
 
-  void AddRuleset(TestRulesetInfo info) {
-    rulesets_.push_back(std::move(info));
-  }
+  void AddRuleset(const TestRulesetInfo& info) { rulesets_.push_back(info); }
 
  private:
   std::vector<TestRulesetInfo> rulesets_;
@@ -691,12 +690,8 @@
   }
   base::Value rules_value = std::move(*ToListValue(rules));
 
-  for (size_t i = 0; i < kNumRulesets; ++i) {
-    TestRulesetInfo info;
-    info.relative_file_path = std::to_string(i);
-    info.rules_value = rules_value.Clone();
-    AddRuleset(std::move(info));
-  }
+  for (size_t i = 0; i < kNumRulesets; ++i)
+    AddRuleset(TestRulesetInfo(std::to_string(i), rules_value));
 
   LoadAndExpectSuccess(kNumRulesets *
                        kRulesPerRuleset /* expected_indexed_rules_count */);
@@ -712,12 +707,8 @@
 TEST_P(MultipleRulesetsIndexingTest, EmptyRulesets) {
   size_t kNumRulesets = 7;
 
-  for (size_t i = 0; i < kNumRulesets; ++i) {
-    TestRulesetInfo info;
-    info.relative_file_path = std::to_string(i);
-    info.rules_value = base::ListValue();
-    AddRuleset(std::move(info));
-  }
+  for (size_t i = 0; i < kNumRulesets; ++i)
+    AddRuleset(TestRulesetInfo(std::to_string(i), base::ListValue()));
 
   LoadAndExpectSuccess(0u /* expected_indexed_rules_count */);
 }
@@ -725,30 +716,15 @@
 // Tests an extension with multiple static rulesets, with one of rulesets
 // specifying an invalid rules file.
 TEST_P(MultipleRulesetsIndexingTest, ListNotPassed) {
-  {
     std::vector<TestRule> rules({CreateGenericRule()});
-    TestRulesetInfo info1;
-    info1.relative_file_path = "1";
-    info1.rules_value = std::move(*ToListValue(rules));
-    AddRuleset(std::move(info1));
-  }
+    AddRuleset(TestRulesetInfo("1", *ToListValue(rules)));
 
-  {
     // Persist a ruleset with an invalid rules file.
-    TestRulesetInfo info2;
-    info2.relative_file_path = "2";
-    info2.rules_value = base::DictionaryValue();
-    AddRuleset(std::move(info2));
-  }
+    AddRuleset(TestRulesetInfo("2", base::DictionaryValue()));
 
-  {
-    TestRulesetInfo info3;
-    info3.relative_file_path = "3";
-    info3.rules_value = base::ListValue();
-    AddRuleset(std::move(info3));
-  }
+    AddRuleset(TestRulesetInfo("3", base::ListValue()));
 
-  LoadAndExpectError(kErrorListNotPassed, "2" /* filename */);
+    LoadAndExpectError(kErrorListNotPassed, "2" /* filename */);
 }
 
 // Tests an extension with multiple static rulesets with each ruleset generating
@@ -768,14 +744,12 @@
     rule.condition->regex_filter = kLargeRegexFilter;
     rules.push_back(rule);
 
-    TestRulesetInfo info;
-    info.relative_file_path = "1.json";
-    info.rules_value = std::move(*ToListValue(rules));
+    TestRulesetInfo info("1.json", *ToListValue(rules));
 
     expected_warnings.push_back(
         GetLargeRegexWarning(*rule.id, info.relative_file_path).message);
 
-    AddRuleset(std::move(info));
+    AddRuleset(info);
 
     expected_rule_count += rules.size();
   }
@@ -789,14 +763,12 @@
       rules.push_back(rule);
     }
 
-    TestRulesetInfo info;
-    info.relative_file_path = "2.json";
-    info.rules_value = std::move(*ToListValue(rules));
+    TestRulesetInfo info("2.json", *ToListValue(rules));
 
     expected_warnings.push_back(
         GetErrorWithFilename(kRuleCountExceeded, info.relative_file_path));
 
-    AddRuleset(std::move(info));
+    AddRuleset(info);
 
     expected_rule_count += dnr_api::MAX_NUMBER_OF_RULES;
   }
@@ -823,14 +795,12 @@
       rules.push_back(rule);
     }
 
-    TestRulesetInfo info;
-    info.relative_file_path = "3.json";
-    info.rules_value = std::move(*ToListValue(rules));
+    TestRulesetInfo info("3.json", *ToListValue(rules));
 
     expected_warnings.push_back(
         GetErrorWithFilename(kRegexRuleCountExceeded, info.relative_file_path));
 
-    AddRuleset(std::move(info));
+    AddRuleset(info);
 
     expected_rule_count +=
         kCountNonRegexRules + dnr_api::MAX_NUMBER_OF_REGEX_RULES;
diff --git a/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
index 1a3e1fba..7806a9d 100644
--- a/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
@@ -72,7 +72,7 @@
                            ? ConfigFlag::kConfig_HasBackgroundScript
                            : ConfigFlag::kConfig_None;
 
-    TestRulesetInfo info = {kJSONRulesFilename, std::move(*ToListValue(rules))};
+    TestRulesetInfo info(kJSONRulesFilename, *ToListValue(rules));
     WriteManifestAndRuleset(extension_dir, info, host_permissions, flags);
 
     last_loaded_extension_ =
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
index ea817b1..2067c75 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/scoped_observer.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/threading/thread_restrictions.h"
@@ -179,6 +180,44 @@
     return LoadExtensionWithFlags(path, flags);
   }
 
+  void RunUpdateTest(base::StringPiece path, bool expect_failure) {
+    ExtensionTestMessageListener ready_listener("ready", true);
+    ASSERT_TRUE(embedded_test_server()->Start());
+    const Extension* extension =
+        LoadExtensionWithParamFlags(test_data_dir_.AppendASCII(path));
+    ASSERT_TRUE(extension) << message_;
+    // Test that there is a browser action in the toolbar.
+    ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions());
+
+    ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
+    ExtensionAction* action = GetBrowserAction(browser(), *extension);
+    EXPECT_EQ("This is the default title.",
+              action->GetTitle(ExtensionAction::kDefaultTabId));
+    EXPECT_EQ(
+        "", action->GetExplicitlySetBadgeText(ExtensionAction::kDefaultTabId));
+    EXPECT_EQ(SkColorSetARGB(0, 0, 0, 0),
+              action->GetBadgeBackgroundColor(ExtensionAction::kDefaultTabId));
+
+    // Tell the extension to update the browser action state and then
+    // catch the result.
+    ResultCatcher catcher;
+    ready_listener.Reply("update");
+
+    if (expect_failure) {
+      EXPECT_FALSE(catcher.GetNextResult());
+      EXPECT_EQ("The source image could not be decoded.", catcher.message());
+      return;
+    }
+
+    EXPECT_TRUE(catcher.GetNextResult());
+    // Test that we received the changes.
+    EXPECT_EQ("Modified", action->GetTitle(ExtensionAction::kDefaultTabId));
+    EXPECT_EQ("badge", action->GetExplicitlySetBadgeText(
+                           ExtensionAction::kDefaultTabId));
+    EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255),
+              action->GetBadgeBackgroundColor(ExtensionAction::kDefaultTabId));
+  }
+
  private:
   base::test::ScopedFeatureList feature_list_;
   std::unique_ptr<extensions::ScopedWorkerBasedExtensionsChannel>
@@ -209,37 +248,18 @@
   EXPECT_TRUE(catcher.GetNextResult());
 }
 
-using BrowserActionApiUpdateLazyTest = BrowserActionApiLazyTest;
-IN_PROC_BROWSER_TEST_P(BrowserActionApiUpdateLazyTest, Update) {
-  ExtensionTestMessageListener ready_listener("ready", true);
-  ASSERT_TRUE(embedded_test_server()->Start());
-  const Extension* extension = LoadExtensionWithParamFlags(
-      test_data_dir_.AppendASCII("browser_action/update"));
-  ASSERT_TRUE(extension) << message_;
-  // Test that there is a browser action in the toolbar.
-  ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions());
+IN_PROC_BROWSER_TEST_P(BrowserActionApiLazyTest, Update) {
+  ASSERT_NO_FATAL_FAILURE(RunUpdateTest("browser_action/update", false))
+      << GetParam();
+}
 
-  ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
-  ExtensionAction* action = GetBrowserAction(browser(), *extension);
-  EXPECT_EQ("This is the default title.",
-            action->GetTitle(ExtensionAction::kDefaultTabId));
-  EXPECT_EQ("",
-            action->GetExplicitlySetBadgeText(ExtensionAction::kDefaultTabId));
-  EXPECT_EQ(SkColorSetARGB(0, 0, 0, 0),
-            action->GetBadgeBackgroundColor(ExtensionAction::kDefaultTabId));
-
-  // Tell the extension to update the browser action state and then
-  // catch the result.
-  ResultCatcher catcher;
-  ready_listener.Reply("update");
-  ASSERT_TRUE(catcher.GetNextResult());
-
-  // Test that we received the changes.
-  EXPECT_EQ("Modified", action->GetTitle(ExtensionAction::kDefaultTabId));
-  EXPECT_EQ("badge",
-            action->GetExplicitlySetBadgeText(ExtensionAction::kDefaultTabId));
-  EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255),
-            action->GetBadgeBackgroundColor(ExtensionAction::kDefaultTabId));
+IN_PROC_BROWSER_TEST_P(BrowserActionApiLazyTest, UpdateSvg) {
+  // TODO(crbug.com/1064671): Service Workers currently don't support loading
+  // SVG images.
+  const bool expect_failure = GetParam() & kUseServiceWorker;
+  ASSERT_NO_FATAL_FAILURE(
+      RunUpdateTest("browser_action/update_svg", expect_failure))
+      << GetParam();
 }
 
 INSTANTIATE_TEST_SUITE_P(EventPageAndLegacyToolbar,
@@ -256,22 +276,6 @@
                          ::testing::Values(kUseServiceWorker |
                                            kUseExtensionsMenuUi));
 
-INSTANTIATE_TEST_SUITE_P(EventPageAndLegacyToolbar,
-                         BrowserActionApiUpdateLazyTest,
-                         ::testing::Values(kNone));
-INSTANTIATE_TEST_SUITE_P(EventPageAndExtensionsMenu,
-                         BrowserActionApiUpdateLazyTest,
-                         ::testing::Values(kUseExtensionsMenuUi));
-// TODO(crbug.com/1015136): Enable these once setIcon works in Service worker
-// extensions. Also, combine this suite with BrowserActionApiLazyTest.
-// INSTANTIATE_TEST_SUITE_P(ServiceWorkerAndLegacyToolbar,
-//                          BrowserActionApiUpdateLazyTest,
-//                          ::testing::Values(kUseServiceWorker));
-// INSTANTIATE_TEST_SUITE_P(ServiceWorkerAndExtensionsMenu,
-//                          BrowserActionApiUpdateLazyTest,
-//                          ::testing::Values(kUseServiceWorker |
-//                                            kUseExtensionsMenuUi));
-
 IN_PROC_BROWSER_TEST_F(BrowserActionApiCanvasTest, DynamicBrowserAction) {
   ASSERT_TRUE(RunExtensionTest("browser_action/no_icon")) << message_;
   const Extension* extension = GetSingleLoadedExtension();
diff --git a/chrome/browser/extensions/api/extension_action/extension_action_api_unittest.cc b/chrome/browser/extensions/api/extension_action/extension_action_api_unittest.cc
index cbd0be1..2e63984 100644
--- a/chrome/browser/extensions/api/extension_action/extension_action_api_unittest.cc
+++ b/chrome/browser/extensions/api/extension_action/extension_action_api_unittest.cc
@@ -9,9 +9,9 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_service_test_with_install.h"
 #include "chrome/common/extensions/api/extension_action/action_info.h"
+#include "chrome/common/extensions/api/extension_action/action_info_test_util.h"
 #include "chrome/common/extensions/extension_test_util.h"
 #include "extensions/common/features/feature_channel.h"
-#include "extensions/common/manifest_constants.h"
 #include "extensions/test/test_extension_dir.h"
 
 namespace extensions {
@@ -26,32 +26,6 @@
             extension_test_util::GetOverrideChannelForActionType(GetParam())) {}
   ~ExtensionActionAPIUnitTest() override {}
 
-  const char* GetManifestKey() {
-    switch (GetParam()) {
-      case ActionInfo::TYPE_BROWSER:
-        return manifest_keys::kBrowserAction;
-      case ActionInfo::TYPE_PAGE:
-        return manifest_keys::kPageAction;
-      case ActionInfo::TYPE_ACTION:
-        return manifest_keys::kAction;
-    }
-    NOTREACHED();
-    return nullptr;
-  }
-
-  const ActionInfo* GetActionInfo(const Extension& extension) {
-    switch (GetParam()) {
-      case ActionInfo::TYPE_BROWSER:
-        return ActionInfo::GetBrowserActionInfo(&extension);
-      case ActionInfo::TYPE_PAGE:
-        return ActionInfo::GetPageActionInfo(&extension);
-      case ActionInfo::TYPE_ACTION:
-        return ActionInfo::GetExtensionActionInfo(&extension);
-    }
-    NOTREACHED();
-    return nullptr;
-  }
-
  private:
   std::unique_ptr<ScopedCurrentChannel> current_channel_;
 
@@ -78,8 +52,8 @@
          })";
 
   TestExtensionDir test_extension_dir;
-  test_extension_dir.WriteManifest(
-      base::StringPrintf(kManifestTemplate, GetManifestKey()));
+  test_extension_dir.WriteManifest(base::StringPrintf(
+      kManifestTemplate, GetManifestKeyForActionType(GetParam())));
 
   {
     std::string icon_file_content;
@@ -96,7 +70,7 @@
   const Extension* extension =
       PackAndInstallCRX(test_extension_dir.UnpackedPath(), INSTALL_NEW);
   EXPECT_TRUE(extension->install_warnings().empty());
-  const ActionInfo* action_info = GetActionInfo(*extension);
+  const ActionInfo* action_info = GetActionInfoOfType(*extension, GetParam());
   ASSERT_TRUE(action_info);
 
   const ExtensionIconSet& icons = action_info->default_icon;
diff --git a/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc b/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc
index 70f89b7e..be0c9ea0 100644
--- a/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc
+++ b/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/extensions/extension_action_test_helper.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/extensions/api/extension_action/action_info_test_util.h"
 #include "chrome/common/extensions/extension_test_util.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/sessions/content/session_tab_helper.h"
@@ -34,7 +35,6 @@
 #include "extensions/browser/state_store.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/features/feature_channel.h"
-#include "extensions/common/manifest_constants.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/result_catcher.h"
 #include "extensions/test/test_extension_dir.h"
@@ -182,19 +182,6 @@
   ExtensionActionAPITest() {}
   ~ExtensionActionAPITest() override {}
 
-  const char* GetManifestKey(ActionInfo::Type action_type) {
-    switch (action_type) {
-      case ActionInfo::TYPE_ACTION:
-        return manifest_keys::kAction;
-      case ActionInfo::TYPE_BROWSER:
-        return manifest_keys::kBrowserAction;
-      case ActionInfo::TYPE_PAGE:
-        return manifest_keys::kPageAction;
-    }
-    NOTREACHED();
-    return nullptr;
-  }
-
   const char* GetAPIName(ActionInfo::Type action_type) {
     switch (action_type) {
       case ActionInfo::TYPE_ACTION:
@@ -369,8 +356,8 @@
            "%s": {}
          })";
 
-  test_dir.WriteManifest(
-      base::StringPrintf(kManifestTemplate, GetManifestKey(GetParam())));
+  test_dir.WriteManifest(base::StringPrintf(
+      kManifestTemplate, GetManifestKeyForActionType(GetParam())));
   const Extension* extension = LoadExtension(test_dir.UnpackedPath());
   ASSERT_TRUE(extension);
 
@@ -426,8 +413,8 @@
            }
          })";
 
-  test_dir.WriteManifest(
-      base::StringPrintf(kManifestTemplate, GetManifestKey(GetParam())));
+  test_dir.WriteManifest(base::StringPrintf(
+      kManifestTemplate, GetManifestKeyForActionType(GetParam())));
   const Extension* extension = LoadExtension(test_dir.UnpackedPath());
   ASSERT_TRUE(extension);
 
@@ -467,8 +454,8 @@
          });)";
 
   TestExtensionDir test_dir;
-  test_dir.WriteManifest(
-      base::StringPrintf(kManifestTemplate, GetManifestKey(GetParam())));
+  test_dir.WriteManifest(base::StringPrintf(
+      kManifestTemplate, GetManifestKeyForActionType(GetParam())));
   test_dir.WriteFile(
       FILE_PATH_LITERAL("background.js"),
       base::StringPrintf(kBackgroundJsTemplate, GetAPIName(GetParam())));
@@ -518,8 +505,8 @@
       "window.onload = function() { chrome.test.notifyPass(); };";
 
   TestExtensionDir test_dir;
-  test_dir.WriteManifest(
-      base::StringPrintf(kManifestTemplate, GetManifestKey(GetParam())));
+  test_dir.WriteManifest(base::StringPrintf(
+      kManifestTemplate, GetManifestKeyForActionType(GetParam())));
   test_dir.WriteFile(FILE_PATH_LITERAL("popup.html"), kPopupHtml);
   test_dir.WriteFile(FILE_PATH_LITERAL("popup.js"), kPopupJs);
 
@@ -592,8 +579,8 @@
   }
 
   TestExtensionDir test_dir;
-  test_dir.WriteManifest(
-      base::StringPrintf(kManifestTemplate, GetManifestKey(GetParam())));
+  test_dir.WriteManifest(base::StringPrintf(
+      kManifestTemplate, GetManifestKeyForActionType(GetParam())));
   test_dir.WriteFile(
       FILE_PATH_LITERAL("background.js"),
       base::StringPrintf(kBackgroundJsTemplate, GetAPIName(GetParam())));
@@ -710,8 +697,8 @@
       "<!doctype html><html><body>Blank</body></html>";
 
   TestExtensionDir test_dir;
-  test_dir.WriteManifest(
-      base::StringPrintf(kManifestTemplate, GetManifestKey(GetParam())));
+  test_dir.WriteManifest(base::StringPrintf(
+      kManifestTemplate, GetManifestKeyForActionType(GetParam())));
   test_dir.WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundJs);
   test_dir.WriteFile(FILE_PATH_LITERAL("default_popup.html"), kPopupHtml);
   test_dir.WriteFile(FILE_PATH_LITERAL("custom_popup1.html"), kPopupHtml);
@@ -896,8 +883,8 @@
          })";
 
   TestExtensionDir test_dir;
-  test_dir.WriteManifest(
-      base::StringPrintf(kManifestTemplate, GetManifestKey(GetParam())));
+  test_dir.WriteManifest(base::StringPrintf(
+      kManifestTemplate, GetManifestKeyForActionType(GetParam())));
   test_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
                      "// This space left blank.");
   const Extension* extension = LoadExtension(test_dir.UnpackedPath());
diff --git a/chrome/browser/extensions/app_process_apitest.cc b/chrome/browser/extensions/app_process_apitest.cc
index fe17c96..c808594 100644
--- a/chrome/browser/extensions/app_process_apitest.cc
+++ b/chrome/browser/extensions/app_process_apitest.cc
@@ -154,17 +154,12 @@
 
 // Tests that hosted apps with the background permission get a process-per-app
 // model, since all pages need to be able to script the background page.
-// http://crbug.com/172750
-IN_PROC_BROWSER_TEST_F(AppApiTest, DISABLED_AppProcess) {
-  LOG(INFO) << "Start of test.";
-
+IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcess) {
   extensions::ProcessMap* process_map =
       extensions::ProcessMap::Get(browser()->profile());
 
   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("app_process")));
 
-  LOG(INFO) << "Loaded extension.";
-
   // Open two tabs in the app, one outside it.
   GURL base_url = GetTestBaseURL("app_process");
 
@@ -182,7 +177,6 @@
                                         ->GetProcess()
                                         ->GetID()));
   EXPECT_FALSE(browser()->tab_strip_model()->GetWebContentsAt(1)->GetWebUI());
-  LOG(INFO) << "Nav 1.";
 
   ui_test_utils::NavigateToURLWithDisposition(
       browser(), base_url.Resolve("path2/empty.html"),
@@ -195,14 +189,11 @@
                                         ->GetProcess()
                                         ->GetID()));
   EXPECT_FALSE(browser()->tab_strip_model()->GetWebContentsAt(2)->GetWebUI());
-  LOG(INFO) << "Nav 2.";
 
   ui_test_utils::TabAddedWaiter tab_add(browser());
   chrome::NewTab(browser());
   tab_add.Wait();
-  LOG(INFO) << "New tab.";
   ui_test_utils::NavigateToURL(browser(), base_url.Resolve("path3/empty.html"));
-  LOG(INFO) << "Nav 3.";
   EXPECT_FALSE(process_map->Contains(browser()
                                          ->tab_strip_model()
                                          ->GetWebContentsAt(3)
@@ -232,16 +223,13 @@
   // Now let's do the same using window.open. The same should happen.
   ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
   OpenWindow(tab, base_url.Resolve("path1/empty.html"), true, true, NULL);
-  LOG(INFO) << "WindowOpenHelper 1.";
   OpenWindow(tab, base_url.Resolve("path2/empty.html"), true, true, NULL);
-  LOG(INFO) << "WindowOpenHelper 2.";
   // TODO(creis): This should open in a new process (i.e., false for the last
   // argument), but we temporarily avoid swapping processes away from a hosted
   // app if it has an opener, because some OAuth providers make script calls
   // between non-app popups and non-app iframes in the app process.
   // See crbug.com/59285.
   OpenWindow(tab, base_url.Resolve("path3/empty.html"), true, true, NULL);
-  LOG(INFO) << "WindowOpenHelper 3.";
 
   // Now let's have these pages navigate, into or out of the extension web
   // extent. They should switch processes.
@@ -249,10 +237,8 @@
   const GURL& non_app_url(base_url.Resolve("path3/empty.html"));
   NavigateInRenderer(browser()->tab_strip_model()->GetWebContentsAt(2),
                      non_app_url);
-  LOG(INFO) << "NavigateTabHelper 1.";
   NavigateInRenderer(browser()->tab_strip_model()->GetWebContentsAt(3),
                      app_url);
-  LOG(INFO) << "NavigateTabHelper 2.";
   EXPECT_NE(tab->GetMainFrame()->GetProcess(), browser()
                                                    ->tab_strip_model()
                                                    ->GetWebContentsAt(2)
@@ -268,7 +254,6 @@
   // be valid.
   NavigateInRenderer(browser()->tab_strip_model()->GetWebContentsAt(6),
                      app_url);
-  LOG(INFO) << "NavigateTabHelper 3.";
   EXPECT_EQ(tab->GetMainFrame()->GetProcess(), browser()
                                                    ->tab_strip_model()
                                                    ->GetWebContentsAt(6)
@@ -280,8 +265,6 @@
       "window.domAutomationController.send(window.opener != null)",
       &windowOpenerValid));
   ASSERT_TRUE(windowOpenerValid);
-
-  LOG(INFO) << "End of test.";
 }
 
 // Test that hosted apps without the background permission use a process per app
diff --git a/chrome/browser/extensions/browsertest_util.cc b/chrome/browser/extensions/browsertest_util.cc
index b5b86ac4..c5cae3b 100644
--- a/chrome/browser/extensions/browsertest_util.cc
+++ b/chrome/browser/extensions/browsertest_util.cc
@@ -21,14 +21,8 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/web_applications/components/install_manager.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/components/web_app_provider_base.h"
-#include "chrome/browser/web_applications/components/web_app_tab_helper_base.h"
 #include "chrome/common/chrome_features.h"
-#include "chrome/common/web_application_info.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_utils.h"
@@ -58,39 +52,6 @@
 #endif
 }
 
-const Extension* InstallBookmarkApp(Profile* profile, WebApplicationInfo info) {
-  size_t num_extensions =
-      ExtensionRegistry::Get(profile)->enabled_extensions().size();
-
-  base::RunLoop run_loop;
-  web_app::AppId app_id;
-  auto* provider = web_app::WebAppProviderBase::GetProviderBase(profile);
-  DCHECK(provider);
-  provider->install_manager().InstallWebAppFromInfo(
-      std::make_unique<WebApplicationInfo>(info),
-      web_app::ForInstallableSite::kYes,
-      /*install_source=*/WebappInstallSource::OMNIBOX_INSTALL_ICON,
-      base::BindLambdaForTesting([&](const web_app::AppId& installed_app_id,
-                                     web_app::InstallResultCode code) {
-        DCHECK_EQ(web_app::InstallResultCode::kSuccessNewInstall, code);
-        app_id = installed_app_id;
-        run_loop.Quit();
-      }));
-
-  const Extension* app = nullptr;
-  run_loop.Run();
-  app = ExtensionRegistry::Get(profile)->enabled_extensions().GetByID(app_id);
-
-  EXPECT_EQ(++num_extensions,
-            ExtensionRegistry::Get(profile)->enabled_extensions().size());
-  DCHECK(app);
-  extensions::SetLaunchType(profile, app->id(),
-                            info.open_as_window
-                                ? extensions::LAUNCH_TYPE_WINDOW
-                                : extensions::LAUNCH_TYPE_REGULAR);
-  return app;
-}
-
 Browser* LaunchAppBrowser(Profile* profile, const Extension* extension_app) {
   EXPECT_TRUE(
       apps::AppServiceProxyFactory::GetForProfile(profile)
diff --git a/chrome/browser/extensions/browsertest_util.h b/chrome/browser/extensions/browsertest_util.h
index 2f189b1b..eef35ae6 100644
--- a/chrome/browser/extensions/browsertest_util.h
+++ b/chrome/browser/extensions/browsertest_util.h
@@ -8,7 +8,6 @@
 class Browser;
 class GURL;
 class Profile;
-struct WebApplicationInfo;
 
 namespace content {
 class WebContents;
@@ -26,9 +25,6 @@
 // actual production devices, but some tests need to do it manually.
 void CreateAndInitializeLocalCache();
 
-// Installs a Bookmark App into |profile| using |info|.
-const Extension* InstallBookmarkApp(Profile* profile, WebApplicationInfo info);
-
 // Launches a new app window for |app| in |profile|.
 Browser* LaunchAppBrowser(Profile* profile, const Extension* app);
 
diff --git a/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc b/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc
index 2812057..b6667a89 100644
--- a/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc
+++ b/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc
@@ -98,6 +98,12 @@
  public:
   CorbAndCorsExtensionTestBase() = default;
 
+  bool AllowFileAccessFromFiles() override {
+    // This is important to 1) test what we ship and 2) make sure that
+    // file->file XHRs are blocked by CORS (without extensions in the picture).
+    return false;
+  }
+
   void SetUpOnMainThread() override {
     ExtensionBrowserTest::SetUpOnMainThread();
 
@@ -986,28 +992,66 @@
   ui_test_utils::NavigateToURL(browser(), page_url);
   ASSERT_EQ(page_url,
             active_web_contents()->GetMainFrame()->GetLastCommittedURL());
+  const char kScriptTemplate[] = R"(
+      const url = $1;
+      const xhr = new XMLHttpRequest();
+      xhr.onload = () => domAutomationController.send(xhr.responseText);
+      xhr.onerror = () => domAutomationController.send('XHR ERROR');
+      xhr.open("GET", url);
+      xhr.send()
+  )";
+  std::string script = content::JsReplace(kScriptTemplate, same_dir_resource);
 
-  // Inject a content script that performs a cross-origin fetch from another
-  // file: URL (all file: URLs are treated as an opaque origin, so all such
-  // fetches would be considered cross-origin).
+  // Sanity check: file: -> file: XHR (no extensions involved) should be blocked
+  // by CORS equivalent inside FileURLLoaderFactory.  (All file: URLs are
+  // treated as an opaque origin, so all such XHRs would be considered
+  // cross-origin.)
+  {
+    base::HistogramTester histograms;
+    content::DOMMessageQueue queue;
+    ExecuteScriptAsync(active_web_contents(), script);
+    std::string xhr_result = PopString(&queue);
+
+    // Verify that the XHR was blocked by CORS-equivalent in
+    // FileURLLoaderFactory.
+    EXPECT_EQ("XHR ERROR", xhr_result);
+
+    // CORB is not used from FileURLLoaderFactory - verify that no CORB UMAs
+    // have been logged.
+    SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
+    EXPECT_EQ(
+        0u,
+        histograms.GetTotalCountsForPrefix("SiteIsolation.XSD.Browser").size());
+  }
+
+  // Inject a content script that performs a cross-origin XHR from another file:
+  // URL (all file: URLs are treated as an opaque origin, so all such XHRs would
+  // be considered cross-origin).
   //
   // The ability to inject content scripts into file: URLs comes from a
   // combination of <all_urls> and granting file access to the extension.
-  base::HistogramTester histograms;
-  std::string fetch_result =
-      FetchViaContentScript(same_dir_resource, active_web_contents());
+  //
+  // The script below uses the XMLHttpRequest API, rather than fetch API,
+  // because the fetch API doesn't support file: requests currently
+  // (see https://crbug.com/1051594#c9 and https://crbug.com/1051597#c19).
+  {
+    base::HistogramTester histograms;
+    content::DOMMessageQueue queue;
+    ExecuteContentScript(active_web_contents(), script);
+    std::string xhr_result = PopString(&queue);
 
-  // Verify that the fetch was blocked by CORS-equivalent in
-  // FileURLLoaderFactory (even though the extension has <all_urls> permission
-  // and was granted file access).
-  EXPECT_EQ(kCorsErrorWhenFetching, fetch_result);
+    // Verify that the XHR was blocked by CORS-equivalent in
+    // FileURLLoaderFactory (even though the extension has <all_urls> permission
+    // and was granted file access).
+    EXPECT_EQ("XHR ERROR", xhr_result);
 
-  // CORB is not used from FileURLLoaderFactory - verify that no CORB UMAs have
-  // been logged.
-  SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
-  EXPECT_EQ(
-      0u,
-      histograms.GetTotalCountsForPrefix("SiteIsolation.XSD.Browser").size());
+    // CORB is not used from FileURLLoaderFactory - verify that no CORB UMAs
+    // have been logged.
+    SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
+    EXPECT_EQ(
+        0u,
+        histograms.GetTotalCountsForPrefix("SiteIsolation.XSD.Browser").size());
+  }
 }
 
 // Coverage of *.subdomain.com extension permissions for CORB-eligible fetches
diff --git a/chrome/browser/extensions/extension_action_manager_unittest.cc b/chrome/browser/extensions/extension_action_manager_unittest.cc
index b81648e..b11622f 100644
--- a/chrome/browser/extensions/extension_action_manager_unittest.cc
+++ b/chrome/browser/extensions/extension_action_manager_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "chrome/browser/extensions/extension_action.h"
+#include "chrome/common/extensions/api/extension_action/action_info_test_util.h"
 #include "chrome/common/extensions/extension_test_util.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/version_info/channel.h"
@@ -14,7 +15,6 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension_builder.h"
 #include "extensions/common/features/feature_channel.h"
-#include "extensions/common/manifest_constants.h"
 #include "extensions/common/manifest_handlers/icons_handler.h"
 #include "extensions/common/value_builder.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -30,23 +30,6 @@
   ExtensionActionManagerTest();
 
  protected:
-  const char* GetManifestKey() {
-    const char* key = nullptr;
-    switch (GetParam()) {
-      case ActionInfo::TYPE_ACTION:
-        key = manifest_keys::kAction;
-        break;
-      case ActionInfo::TYPE_PAGE:
-        key = manifest_keys::kPageAction;
-        break;
-      case ActionInfo::TYPE_BROWSER:
-        key = manifest_keys::kBrowserAction;
-        break;
-    }
-
-    return key;
-  }
-
   ExtensionActionManager* manager() { return manager_; }
   ExtensionRegistry* registry() { return registry_; }
 
@@ -82,7 +65,7 @@
                                        .Set("48", "icon48.png")
                                        .Set("128", "icon128.png")
                                        .Build())
-          .SetManifestKey(GetManifestKey(),
+          .SetManifestKey(GetManifestKeyForActionType(GetParam()),
                           std::make_unique<base::DictionaryValue>())
           .Build();
 
@@ -102,7 +85,7 @@
 TEST_P(ExtensionActionManagerTest, TestPopulateMissingValues_Title) {
   scoped_refptr<const Extension> extension =
       ExtensionBuilder("Test Extension")
-          .SetManifestKey(GetManifestKey(),
+          .SetManifestKey(GetManifestKeyForActionType(GetParam()),
                           std::make_unique<base::DictionaryValue>())
           .Build();
 
@@ -124,7 +107,7 @@
           .SetManifestKey("icons",
                           DictionaryBuilder().Set("24", "icon24.png").Build())
           .SetManifestKey(
-              GetManifestKey(),
+              GetManifestKeyForActionType(GetParam()),
               DictionaryBuilder()
                   .Set("default_icon",
                        DictionaryBuilder().Set("19", "icon19.png").Build())
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index 723185b..ba028116 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -45,10 +45,8 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/extension_message_bubble_factory.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/web_applications/extensions/web_app_extension_shortcut.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/web_application_info.h"
 #include "components/crx_file/crx_verifier.h"
 #include "components/sync/model/string_ordinal.h"
 #include "components/version_info/version_info.h"
@@ -519,11 +517,6 @@
                                   browser(), Extension::NO_FLAGS, false, false);
 }
 
-const Extension* ExtensionBrowserTest::InstallBookmarkApp(
-    WebApplicationInfo info) {
-  return browsertest_util::InstallBookmarkApp(profile(), std::move(info));
-}
-
 const Extension* ExtensionBrowserTest::InstallExtensionFromWebstore(
     const base::FilePath& path,
     int expected_change) {
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index d4d4c343..c8ab4de 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -34,7 +34,6 @@
 #include "extensions/common/manifest.h"
 
 class Profile;
-struct WebApplicationInfo;
 
 namespace extensions {
 class ExtensionCacheFake;
@@ -231,9 +230,6 @@
         Manifest::INTERNAL, browser(), Extension::NO_FLAGS, false, true);
   }
 
-  // Installs bookmark app for |info|.
-  const Extension* InstallBookmarkApp(WebApplicationInfo info);
-
   // Installs extension as if it came from the Chrome Webstore.
   const Extension* InstallExtensionFromWebstore(const base::FilePath& path,
                                                 int expected_change);
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 0121c2e9..677360d1 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -113,6 +113,11 @@
     "expiry_milestone": 81
   },
   {
+    "name": "app-cache",
+    "owners": [ "enne" ],
+    "expiry_milestone": 86
+  },
+  {
     "name": "app-management",
     "owners": [ "//chrome/browser/ui/webui/app_management/OWNERS" ],
     "expiry_milestone": 81
@@ -2692,6 +2697,11 @@
     "expiry_milestone": 90
   },
   {
+    "name": "launcher-settings-search",
+    "owners": [ "jiameng", "tby" ],
+    "expiry_milestone": 88
+  },
+  {
     "name": "legacy-tls-enforced",
     "owners": [ "cthomp" ],
     "expiry_milestone": 87
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index a9fb24a..25cec00 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -115,6 +115,12 @@
 const char kAndroidPictureInPictureAPIDescription[] =
     "Enable Picture-in-Picture Web API for Android";
 
+extern const char kAppCacheName[] = "AppCache web API and browser backend";
+extern const char kAppCacheDescription[] =
+    "When disabled, turns off all AppCache code so that developers "
+    "can test that their code works properly in the future when AppCache "
+    "has been removed.";
+
 const char kDnsHttpssvcName[] = "Support for HTTPSSVC records in DNS.";
 const char kDnsHttpssvcDescription[] =
     "When enabled, Chrome may query a configured DoH server for HTTPSSVC "
@@ -1105,6 +1111,10 @@
     "conflict with the latest JavaScript features. This flag allows disabling "
     "support of those features for compatibility with such pages.";
 
+const char kLauncherSettingsSearchName[] = "Launcher settings search";
+const char kLauncherSettingsSearchDescription[] =
+    "Enable search results for OS settings in the launcher.";
+
 const char kLegacyTLSEnforcedName[] =
     "Enforce deprecation of legacy TLS versions";
 const char kLegacyTLSEnforcedDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index a34fb8c..dff2339 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -96,6 +96,9 @@
 extern const char kAndroidPictureInPictureAPIName[];
 extern const char kAndroidPictureInPictureAPIDescription[];
 
+extern const char kAppCacheName[];
+extern const char kAppCacheDescription[];
+
 extern const char kAutofillAlwaysReturnCloudTokenizedCardName[];
 extern const char kAutofillAlwaysReturnCloudTokenizedCardDescription[];
 
@@ -657,6 +660,9 @@
 extern const char kJavascriptHarmonyShippingName[];
 extern const char kJavascriptHarmonyShippingDescription[];
 
+extern const char kLauncherSettingsSearchName[];
+extern const char kLauncherSettingsSearchDescription[];
+
 extern const char kLegacyTLSEnforcedName[];
 extern const char kLegacyTLSEnforcedDescription[];
 
diff --git a/chrome/browser/media/history/media_history_browsertest.cc b/chrome/browser/media/history/media_history_browsertest.cc
index 00cf545..d8b2e7f 100644
--- a/chrome/browser/media/history/media_history_browsertest.cc
+++ b/chrome/browser/media/history/media_history_browsertest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/media/history/media_history_images_table.h"
 #include "chrome/browser/media/history/media_history_keyed_service.h"
 #include "chrome/browser/media/history/media_history_keyed_service_factory.h"
+#include "chrome/browser/media/history/media_history_origin_table.h"
 #include "chrome/browser/media/history/media_history_session_images_table.h"
 #include "chrome/browser/media/history/media_history_session_table.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/media/history/media_history_feed_items_table.h b/chrome/browser/media/history/media_history_feed_items_table.h
index f08764a..a408a52 100644
--- a/chrome/browser/media/history/media_history_feed_items_table.h
+++ b/chrome/browser/media/history/media_history_feed_items_table.h
@@ -50,7 +50,7 @@
       delete;
 
  private:
-  friend class MediaHistoryStoreInternal;
+  friend class MediaHistoryStore;
 
   explicit MediaHistoryFeedItemsTable(
       scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
diff --git a/chrome/browser/media/history/media_history_feeds_table.cc b/chrome/browser/media/history/media_history_feeds_table.cc
index 33fcf21a..a2cb35a0 100644
--- a/chrome/browser/media/history/media_history_feeds_table.cc
+++ b/chrome/browser/media/history/media_history_feeds_table.cc
@@ -9,6 +9,7 @@
 #include "base/updateable_sequenced_task_runner.h"
 #include "chrome/browser/media/feeds/media_feeds.pb.h"
 #include "chrome/browser/media/feeds/media_feeds_utils.h"
+#include "chrome/browser/media/history/media_history_origin_table.h"
 #include "chrome/browser/media/history/media_history_store.h"
 #include "services/media_session/public/cpp/media_image.h"
 #include "sql/statement.h"
diff --git a/chrome/browser/media/history/media_history_feeds_table.h b/chrome/browser/media/history/media_history_feeds_table.h
index c98b3f6..e7a37bd 100644
--- a/chrome/browser/media/history/media_history_feeds_table.h
+++ b/chrome/browser/media/history/media_history_feeds_table.h
@@ -37,7 +37,7 @@
   };
 
  private:
-  friend class MediaHistoryStoreInternal;
+  friend class MediaHistoryStore;
 
   explicit MediaHistoryFeedsTable(
       scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
diff --git a/chrome/browser/media/history/media_history_images_table.cc b/chrome/browser/media/history/media_history_images_table.cc
index e591cc9..0f1ca96 100644
--- a/chrome/browser/media/history/media_history_images_table.cc
+++ b/chrome/browser/media/history/media_history_images_table.cc
@@ -6,6 +6,7 @@
 
 #include "base/strings/stringprintf.h"
 #include "base/updateable_sequenced_task_runner.h"
+#include "chrome/browser/media/history/media_history_origin_table.h"
 #include "chrome/browser/media/history/media_history_store.h"
 #include "sql/statement.h"
 
diff --git a/chrome/browser/media/history/media_history_images_table.h b/chrome/browser/media/history/media_history_images_table.h
index 434ceac..49182fb 100644
--- a/chrome/browser/media/history/media_history_images_table.h
+++ b/chrome/browser/media/history/media_history_images_table.h
@@ -24,7 +24,7 @@
   static const char kTableName[];
 
  private:
-  friend class MediaHistoryStoreInternal;
+  friend class MediaHistoryStore;
 
   explicit MediaHistoryImagesTable(
       scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
diff --git a/chrome/browser/media/history/media_history_keyed_service.cc b/chrome/browser/media/history/media_history_keyed_service.cc
index 41dae95..6d305ec 100644
--- a/chrome/browser/media/history/media_history_keyed_service.cc
+++ b/chrome/browser/media/history/media_history_keyed_service.cc
@@ -7,6 +7,7 @@
 #include "base/feature_list.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
+#include "base/task_runner_util.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/media/history/media_history_keyed_service_factory.h"
 #include "chrome/browser/media/history/media_history_store.h"
@@ -27,9 +28,11 @@
 // history.
 class MediaHistoryKeyedService::StoreHolder {
  public:
-  explicit StoreHolder(Profile* profile,
-                       std::unique_ptr<MediaHistoryStore> local)
-      : profile_(profile), local_(std::move(local)) {}
+  explicit StoreHolder(
+      Profile* profile,
+      scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner)
+      : profile_(profile),
+        local_(new MediaHistoryStore(profile, std::move(db_task_runner))) {}
   explicit StoreHolder(Profile* profile, MediaHistoryKeyedService* remote)
       : profile_(profile), remote_(remote) {}
 
@@ -59,7 +62,7 @@
 
  private:
   Profile* profile_;
-  std::unique_ptr<MediaHistoryStore> local_;
+  scoped_refptr<MediaHistoryStore> local_;
   MediaHistoryKeyedService* remote_ = nullptr;
 };
 
@@ -82,9 +85,7 @@
         {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
          base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 
-    store_ = std::make_unique<StoreHolder>(
-        profile_, std::make_unique<MediaHistoryStore>(
-                      profile_, std::move(db_task_runner)));
+    store_ = std::make_unique<StoreHolder>(profile_, std::move(db_task_runner));
   }
 }
 
@@ -116,7 +117,14 @@
 
   if (deletion_info.IsAllHistory()) {
     // Destroy the old database and create a new one.
-    store->EraseDatabaseAndCreateNew();
+    auto db_task_runner = store->db_task_runner_;
+
+    db_task_runner->PostTask(FROM_HERE,
+                             base::BindOnce(&MediaHistoryStore::RazeAndClose,
+                                            store_->GetForDelete()));
+
+    // Create a new internal store.
+    store_ = std::make_unique<StoreHolder>(profile_, std::move(db_task_runner));
     return;
   }
 
@@ -138,8 +146,11 @@
     deleted_origins.insert(origin);
   }
 
-  if (!deleted_origins.empty())
-    store->DeleteAllOriginData(deleted_origins);
+  if (!deleted_origins.empty()) {
+    store->db_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&MediaHistoryStore::DeleteAllOriginData,
+                                  store, origins));
+  }
 
   // Build a set of all urls in |deleted_rows| that do not have their origin in
   // |deleted_origins|.
@@ -153,31 +164,48 @@
     deleted_urls.insert(row.url());
   }
 
-  if (!deleted_urls.empty())
-    store->DeleteAllURLData(deleted_urls);
+  if (!deleted_urls.empty()) {
+    store->db_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&MediaHistoryStore::DeleteAllURLData, store,
+                                  deleted_urls));
+  }
 }
 
 void MediaHistoryKeyedService::SavePlayback(
     const content::MediaPlayerWatchTime& watch_time) {
-  if (auto* store = store_->GetForWrite())
-    store->SavePlayback(watch_time);
+  if (auto* store = store_->GetForWrite()) {
+    store->db_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&MediaHistoryStore::SavePlayback, store, watch_time));
+  }
 }
 
 void MediaHistoryKeyedService::GetMediaHistoryStats(
     base::OnceCallback<void(mojom::MediaHistoryStatsPtr)> callback) {
-  store_->GetForRead()->GetMediaHistoryStats(std::move(callback));
+  base::PostTaskAndReplyWithResult(
+      store_->GetForRead()->db_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&MediaHistoryStore::GetMediaHistoryStats,
+                     store_->GetForRead()),
+      std::move(callback));
 }
 
 void MediaHistoryKeyedService::GetOriginRowsForDebug(
     base::OnceCallback<void(std::vector<mojom::MediaHistoryOriginRowPtr>)>
         callback) {
-  store_->GetForRead()->GetOriginRowsForDebug(std::move(callback));
+  base::PostTaskAndReplyWithResult(
+      store_->GetForRead()->db_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&MediaHistoryStore::GetOriginRowsForDebug,
+                     store_->GetForRead()),
+      std::move(callback));
 }
 
 void MediaHistoryKeyedService::GetMediaHistoryPlaybackRowsForDebug(
     base::OnceCallback<void(std::vector<mojom::MediaHistoryPlaybackRowPtr>)>
         callback) {
-  store_->GetForRead()->GetMediaHistoryPlaybackRowsForDebug(
+  base::PostTaskAndReplyWithResult(
+      store_->GetForRead()->db_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&MediaHistoryStore::GetMediaHistoryPlaybackRowsForDebug,
+                     store_->GetForRead()),
       std::move(callback));
 }
 
@@ -186,8 +214,11 @@
     base::Optional<GetPlaybackSessionsFilter> filter,
     base::OnceCallback<
         void(std::vector<mojom::MediaHistoryPlaybackSessionRowPtr>)> callback) {
-  store_->GetForRead()->GetPlaybackSessions(num_sessions, filter,
-                                            std::move(callback));
+  base::PostTaskAndReplyWithResult(
+      store_->GetForRead()->db_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&MediaHistoryStore::GetPlaybackSessions,
+                     store_->GetForRead(), num_sessions, std::move(filter)),
+      std::move(callback));
 }
 
 void MediaHistoryKeyedService::SavePlaybackSession(
@@ -195,16 +226,22 @@
     const media_session::MediaMetadata& metadata,
     const base::Optional<media_session::MediaPosition>& position,
     const std::vector<media_session::MediaImage>& artwork) {
-  if (auto* store = store_->GetForWrite())
-    store->SavePlaybackSession(url, metadata, position, artwork);
+  if (auto* store = store_->GetForWrite()) {
+    store->db_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&MediaHistoryStore::SavePlaybackSession,
+                                  store, url, metadata, position, artwork));
+  }
 }
 
 void MediaHistoryKeyedService::GetItemsForMediaFeedForDebug(
     const int64_t feed_id,
     base::OnceCallback<void(std::vector<media_feeds::mojom::MediaFeedItemPtr>)>
         callback) {
-  store_->GetForRead()->GetItemsForMediaFeedForDebug(feed_id,
-                                                     std::move(callback));
+  base::PostTaskAndReplyWithResult(
+      store_->GetForRead()->db_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&MediaHistoryStore::GetItemsForMediaFeedForDebug,
+                     store_->GetForRead(), feed_id),
+      std::move(callback));
 }
 
 void MediaHistoryKeyedService::StoreMediaFeedFetchResult(
@@ -215,21 +252,29 @@
     const std::vector<media_session::MediaImage>& logos,
     const std::string& display_name) {
   if (auto* store = store_->GetForWrite()) {
-    store->StoreMediaFeedFetchResult(feed_id, std::move(items), result,
-                                     was_fetched_from_cache, logos,
-                                     display_name);
+    store->db_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&MediaHistoryStore::StoreMediaFeedFetchResult,
+                                  store, feed_id, std::move(items), result,
+                                  was_fetched_from_cache, logos, display_name));
   }
 }
 
 void MediaHistoryKeyedService::GetURLsInTableForTest(
     const std::string& table,
     base::OnceCallback<void(std::set<GURL>)> callback) {
-  store_->GetForRead()->GetURLsInTableForTest(table, std::move(callback));
+  base::PostTaskAndReplyWithResult(
+      store_->GetForRead()->db_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&MediaHistoryStore::GetURLsInTableForTest,
+                     store_->GetForRead(), table),
+      std::move(callback));
 }
 
 void MediaHistoryKeyedService::DiscoverMediaFeed(const GURL& url) {
-  if (auto* store = store_->GetForWrite())
-    store->DiscoverMediaFeed(url);
+  if (auto* store = store_->GetForWrite()) {
+    store->db_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&MediaHistoryStore::DiscoverMediaFeed, store, url));
+  }
 }
 
 MediaHistoryKeyedService::PendingSafeSearchCheck::PendingSafeSearchCheck(
@@ -241,24 +286,37 @@
 
 void MediaHistoryKeyedService::GetPendingSafeSearchCheckMediaFeedItems(
     base::OnceCallback<void(PendingSafeSearchCheckList)> callback) {
-  store_->GetForRead()->GetPendingSafeSearchCheckMediaFeedItems(
+  base::PostTaskAndReplyWithResult(
+      store_->GetForRead()->db_task_runner_.get(), FROM_HERE,
+      base::BindOnce(
+          &MediaHistoryStore::GetPendingSafeSearchCheckMediaFeedItems,
+          store_->GetForRead()),
       std::move(callback));
 }
 
 void MediaHistoryKeyedService::StoreMediaFeedItemSafeSearchResults(
     std::map<int64_t, media_feeds::mojom::SafeSearchResult> results) {
-  if (auto* store = store_->GetForWrite())
-    store->StoreMediaFeedItemSafeSearchResults(results);
+  if (auto* store = store_->GetForWrite()) {
+    store->db_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&MediaHistoryStore::StoreMediaFeedItemSafeSearchResults,
+                       store, results));
+  }
 }
 
 void MediaHistoryKeyedService::PostTaskToDBForTest(base::OnceClosure callback) {
-  store_->GetForRead()->PostTaskToDBForTest(std::move(callback));
+  store_->GetForRead()->db_task_runner_->PostTaskAndReply(
+      FROM_HERE, base::DoNothing(), std::move(callback));
 }
 
 void MediaHistoryKeyedService::GetMediaFeedsForDebug(
     base::OnceCallback<void(std::vector<media_feeds::mojom::MediaFeedPtr>)>
         callback) {
-  store_->GetForRead()->GetMediaFeedsForDebug(std::move(callback));
+  base::PostTaskAndReplyWithResult(
+      store_->GetForRead()->db_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&MediaHistoryStore::GetMediaFeedsForDebug,
+                     store_->GetForRead()),
+      std::move(callback));
 }
 
 }  // namespace media_history
diff --git a/chrome/browser/media/history/media_history_keyed_service_unittest.cc b/chrome/browser/media/history/media_history_keyed_service_unittest.cc
index 261f668..000270c 100644
--- a/chrome/browser/media/history/media_history_keyed_service_unittest.cc
+++ b/chrome/browser/media/history/media_history_keyed_service_unittest.cc
@@ -20,6 +20,8 @@
 #include "chrome/browser/media/history/media_history_feed_items_table.h"
 #include "chrome/browser/media/history/media_history_feeds_table.h"
 #include "chrome/browser/media/history/media_history_images_table.h"
+#include "chrome/browser/media/history/media_history_origin_table.h"
+#include "chrome/browser/media/history/media_history_playback_table.h"
 #include "chrome/browser/media/history/media_history_session_images_table.h"
 #include "chrome/browser/media/history/media_history_session_table.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
diff --git a/chrome/browser/media/history/media_history_origin_table.h b/chrome/browser/media/history/media_history_origin_table.h
index b21c42f..5d8a72d 100644
--- a/chrome/browser/media/history/media_history_origin_table.h
+++ b/chrome/browser/media/history/media_history_origin_table.h
@@ -25,7 +25,7 @@
   static std::string GetOriginForStorage(const url::Origin& origin);
 
  private:
-  friend class MediaHistoryStoreInternal;
+  friend class MediaHistoryStore;
 
   explicit MediaHistoryOriginTable(
       scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
diff --git a/chrome/browser/media/history/media_history_playback_table.h b/chrome/browser/media/history/media_history_playback_table.h
index cfc5943f..b7ce848 100644
--- a/chrome/browser/media/history/media_history_playback_table.h
+++ b/chrome/browser/media/history/media_history_playback_table.h
@@ -39,7 +39,7 @@
   bool DeleteURL(const GURL& url) override;
 
  private:
-  friend class MediaHistoryStoreInternal;
+  friend class MediaHistoryStore;
 
   explicit MediaHistoryPlaybackTable(
       scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
diff --git a/chrome/browser/media/history/media_history_session_images_table.h b/chrome/browser/media/history/media_history_session_images_table.h
index 57059c55ef..0785a26 100644
--- a/chrome/browser/media/history/media_history_session_images_table.h
+++ b/chrome/browser/media/history/media_history_session_images_table.h
@@ -30,7 +30,7 @@
   static const char kTableName[];
 
  private:
-  friend class MediaHistoryStoreInternal;
+  friend class MediaHistoryStore;
 
   explicit MediaHistorySessionImagesTable(
       scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
diff --git a/chrome/browser/media/history/media_history_session_table.h b/chrome/browser/media/history/media_history_session_table.h
index 14043a3..6b639214 100644
--- a/chrome/browser/media/history/media_history_session_table.h
+++ b/chrome/browser/media/history/media_history_session_table.h
@@ -33,7 +33,7 @@
   bool DeleteURL(const GURL& url) override;
 
  private:
-  friend class MediaHistoryStoreInternal;
+  friend class MediaHistoryStore;
 
   explicit MediaHistorySessionTable(
       scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
diff --git a/chrome/browser/media/history/media_history_store.cc b/chrome/browser/media/history/media_history_store.cc
index ed9e8829..bfb4aa1f 100644
--- a/chrome/browser/media/history/media_history_store.cc
+++ b/chrome/browser/media/history/media_history_store.cc
@@ -40,96 +40,19 @@
 
 namespace media_history {
 
-// Refcounted as it is created, initialized and destroyed on a different thread
-// from the DB sequence provided to the constructor of this class that is
-// required for all methods performing database access.
-class MediaHistoryStoreInternal
-    : public base::RefCountedThreadSafe<MediaHistoryStoreInternal> {
- private:
-  friend class base::RefCountedThreadSafe<MediaHistoryStoreInternal>;
-  friend class MediaHistoryStore;
+const char MediaHistoryStore::kInitResultHistogramName[] =
+    "Media.History.Init.Result";
 
-  explicit MediaHistoryStoreInternal(
-      Profile* profile,
-      scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
-  virtual ~MediaHistoryStoreInternal();
+const char MediaHistoryStore::kPlaybackWriteResultHistogramName[] =
+    "Media.History.Playback.WriteResult";
 
-  // Opens the database file from the |db_path|. Separated from the
-  // constructor to ease construction/destruction of this object on one thread
-  // and database access on the DB sequence of |db_task_runner_|.
-  void Initialize();
+const char MediaHistoryStore::kSessionWriteResultHistogramName[] =
+    "Media.History.Session.WriteResult";
 
-  sql::InitStatus CreateOrUpgradeIfNeeded();
-  sql::InitStatus InitializeTables();
-  sql::Database* DB();
+const char MediaHistoryStore::kDatabaseSizeKbHistogramName[] =
+    "Media.History.DatabaseSize";
 
-  // Returns a flag indicating whether the origin id was created successfully.
-  bool CreateOriginId(const url::Origin& origin);
-
-  void SavePlayback(const content::MediaPlayerWatchTime& watch_time);
-
-  mojom::MediaHistoryStatsPtr GetMediaHistoryStats();
-  int GetTableRowCount(const std::string& table_name);
-
-  std::vector<mojom::MediaHistoryOriginRowPtr> GetOriginRowsForDebug();
-
-  std::vector<mojom::MediaHistoryPlaybackRowPtr>
-  GetMediaHistoryPlaybackRowsForDebug();
-
-  std::vector<media_feeds::mojom::MediaFeedPtr> GetMediaFeedsForDebug();
-
-  void SavePlaybackSession(
-      const GURL& url,
-      const media_session::MediaMetadata& metadata,
-      const base::Optional<media_session::MediaPosition>& position,
-      const std::vector<media_session::MediaImage>& artwork);
-
-  std::vector<mojom::MediaHistoryPlaybackSessionRowPtr> GetPlaybackSessions(
-      base::Optional<unsigned int> num_sessions,
-      base::Optional<MediaHistoryStore::GetPlaybackSessionsFilter> filter);
-
-  void RazeAndClose();
-  void DeleteAllOriginData(const std::set<url::Origin>& origins);
-  void DeleteAllURLData(const std::set<GURL>& urls);
-
-  std::set<GURL> GetURLsInTableForTest(const std::string& table);
-
-  void DiscoverMediaFeed(const GURL& url);
-
-  void StoreMediaFeedFetchResult(
-      const int64_t feed_id,
-      std::vector<media_feeds::mojom::MediaFeedItemPtr> items,
-      const media_feeds::mojom::FetchResult result,
-      const bool was_fetched_from_cache,
-      const std::vector<media_session::MediaImage>& logos,
-      const std::string& display_name);
-
-  std::vector<media_feeds::mojom::MediaFeedItemPtr>
-  GetItemsForMediaFeedForDebug(const int64_t feed_id);
-
-  MediaHistoryKeyedService::PendingSafeSearchCheckList
-  GetPendingSafeSearchCheckMediaFeedItems();
-
-  void StoreMediaFeedItemSafeSearchResults(
-      std::map<int64_t, media_feeds::mojom::SafeSearchResult> results);
-
-  scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner_;
-  const base::FilePath db_path_;
-  std::unique_ptr<sql::Database> db_;
-  sql::MetaTable meta_table_;
-  scoped_refptr<MediaHistoryOriginTable> origin_table_;
-  scoped_refptr<MediaHistoryPlaybackTable> playback_table_;
-  scoped_refptr<MediaHistorySessionTable> session_table_;
-  scoped_refptr<MediaHistorySessionImagesTable> session_images_table_;
-  scoped_refptr<MediaHistoryImagesTable> images_table_;
-  scoped_refptr<MediaHistoryFeedsTable> feeds_table_;
-  scoped_refptr<MediaHistoryFeedItemsTable> feed_items_table_;
-  bool initialization_successful_;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaHistoryStoreInternal);
-};
-
-MediaHistoryStoreInternal::MediaHistoryStoreInternal(
+MediaHistoryStore::MediaHistoryStore(
     Profile* profile,
     scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner)
     : db_task_runner_(db_task_runner),
@@ -146,9 +69,13 @@
       feed_items_table_(media_feeds::MediaFeedsService::IsEnabled()
                             ? new MediaHistoryFeedItemsTable(db_task_runner_)
                             : nullptr),
-      initialization_successful_(false) {}
+      initialization_successful_(false) {
+  db_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&MediaHistoryStore::Initialize, base::Unretained(this)));
+}
 
-MediaHistoryStoreInternal::~MediaHistoryStoreInternal() {
+MediaHistoryStore::~MediaHistoryStore() {
   db_task_runner_->ReleaseSoon(FROM_HERE, std::move(origin_table_));
   db_task_runner_->ReleaseSoon(FROM_HERE, std::move(playback_table_));
   db_task_runner_->ReleaseSoon(FROM_HERE, std::move(session_table_));
@@ -159,12 +86,12 @@
   db_task_runner_->DeleteSoon(FROM_HERE, std::move(db_));
 }
 
-sql::Database* MediaHistoryStoreInternal::DB() {
+sql::Database* MediaHistoryStore::DB() {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   return db_.get();
 }
 
-void MediaHistoryStoreInternal::SavePlayback(
+void MediaHistoryStore::SavePlayback(
     const content::MediaPlayerWatchTime& watch_time) {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   if (!initialization_successful_)
@@ -225,7 +152,7 @@
       MediaHistoryStore::PlaybackWriteResult::kSuccess);
 }
 
-void MediaHistoryStoreInternal::Initialize() {
+void MediaHistoryStore::Initialize() {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   db_ = std::make_unique<sql::Database>();
   db_->set_histogram_tag("MediaHistory");
@@ -288,7 +215,7 @@
   }
 }
 
-sql::InitStatus MediaHistoryStoreInternal::CreateOrUpgradeIfNeeded() {
+sql::InitStatus MediaHistoryStore::CreateOrUpgradeIfNeeded() {
   if (!db_)
     return sql::INIT_FAILURE;
 
@@ -305,7 +232,7 @@
   return sql::INIT_OK;
 }
 
-sql::InitStatus MediaHistoryStoreInternal::InitializeTables() {
+sql::InitStatus MediaHistoryStore::InitializeTables() {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   sql::InitStatus status = origin_table_->Initialize(db_.get());
   if (status == sql::INIT_OK)
@@ -324,7 +251,7 @@
   return status;
 }
 
-bool MediaHistoryStoreInternal::CreateOriginId(const url::Origin& origin) {
+bool MediaHistoryStore::CreateOriginId(const url::Origin& origin) {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   if (!initialization_successful_)
     return false;
@@ -332,7 +259,7 @@
   return origin_table_->CreateOriginId(origin);
 }
 
-mojom::MediaHistoryStatsPtr MediaHistoryStoreInternal::GetMediaHistoryStats() {
+mojom::MediaHistoryStatsPtr MediaHistoryStore::GetMediaHistoryStats() {
   mojom::MediaHistoryStatsPtr stats(mojom::MediaHistoryStats::New());
 
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
@@ -354,7 +281,7 @@
 }
 
 std::vector<mojom::MediaHistoryOriginRowPtr>
-MediaHistoryStoreInternal::GetOriginRowsForDebug() {
+MediaHistoryStore::GetOriginRowsForDebug() {
   std::vector<mojom::MediaHistoryOriginRowPtr> origins;
 
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
@@ -394,7 +321,7 @@
 }
 
 std::vector<mojom::MediaHistoryPlaybackRowPtr>
-MediaHistoryStoreInternal::GetMediaHistoryPlaybackRowsForDebug() {
+MediaHistoryStore::GetMediaHistoryPlaybackRowsForDebug() {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   if (!initialization_successful_)
     return std::vector<mojom::MediaHistoryPlaybackRowPtr>();
@@ -403,7 +330,7 @@
 }
 
 std::vector<media_feeds::mojom::MediaFeedPtr>
-MediaHistoryStoreInternal::GetMediaFeedsForDebug() {
+MediaHistoryStore::GetMediaFeedsForDebug() {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   if (!initialization_successful_ || !feeds_table_)
     return std::vector<media_feeds::mojom::MediaFeedPtr>();
@@ -411,7 +338,7 @@
   return feeds_table_->GetRows();
 }
 
-int MediaHistoryStoreInternal::GetTableRowCount(const std::string& table_name) {
+int MediaHistoryStore::GetTableRowCount(const std::string& table_name) {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   if (!initialization_successful_)
     return -1;
@@ -427,7 +354,7 @@
   return -1;
 }
 
-void MediaHistoryStoreInternal::SavePlaybackSession(
+void MediaHistoryStore::SavePlaybackSession(
     const GURL& url,
     const media_session::MediaMetadata& metadata,
     const base::Optional<media_session::MediaPosition>& position,
@@ -498,7 +425,7 @@
 }
 
 std::vector<mojom::MediaHistoryPlaybackSessionRowPtr>
-MediaHistoryStoreInternal::GetPlaybackSessions(
+MediaHistoryStore::GetPlaybackSessions(
     base::Optional<unsigned int> num_sessions,
     base::Optional<MediaHistoryStore::GetPlaybackSessionsFilter> filter) {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
@@ -516,7 +443,7 @@
   return sessions;
 }
 
-void MediaHistoryStoreInternal::RazeAndClose() {
+void MediaHistoryStore::RazeAndClose() {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
 
   if (db_ && db_->is_open())
@@ -525,7 +452,7 @@
   sql::Database::Delete(db_path_);
 }
 
-void MediaHistoryStoreInternal::DeleteAllOriginData(
+void MediaHistoryStore::DeleteAllOriginData(
     const std::set<url::Origin>& origins) {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   if (!initialization_successful_)
@@ -546,7 +473,7 @@
   DB()->CommitTransaction();
 }
 
-void MediaHistoryStoreInternal::DeleteAllURLData(const std::set<GURL>& urls) {
+void MediaHistoryStore::DeleteAllURLData(const std::set<GURL>& urls) {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   if (!initialization_successful_)
     return;
@@ -585,7 +512,7 @@
   }
 }
 
-std::set<GURL> MediaHistoryStoreInternal::GetURLsInTableForTest(
+std::set<GURL> MediaHistoryStore::GetURLsInTableForTest(
     const std::string& table) {
   std::set<GURL> urls;
 
@@ -604,7 +531,7 @@
   return urls;
 }
 
-void MediaHistoryStoreInternal::DiscoverMediaFeed(const GURL& url) {
+void MediaHistoryStore::DiscoverMediaFeed(const GURL& url) {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   if (!initialization_successful_)
     return;
@@ -626,7 +553,7 @@
   DB()->CommitTransaction();
 }
 
-void MediaHistoryStoreInternal::StoreMediaFeedFetchResult(
+void MediaHistoryStore::StoreMediaFeedFetchResult(
     const int64_t feed_id,
     std::vector<media_feeds::mojom::MediaFeedItemPtr> items,
     const media_feeds::mojom::FetchResult result,
@@ -684,7 +611,7 @@
 }
 
 std::vector<media_feeds::mojom::MediaFeedItemPtr>
-MediaHistoryStoreInternal::GetItemsForMediaFeedForDebug(const int64_t feed_id) {
+MediaHistoryStore::GetItemsForMediaFeedForDebug(const int64_t feed_id) {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
 
   if (!initialization_successful_ || !feed_items_table_)
@@ -694,7 +621,7 @@
 }
 
 MediaHistoryKeyedService::PendingSafeSearchCheckList
-MediaHistoryStoreInternal::GetPendingSafeSearchCheckMediaFeedItems() {
+MediaHistoryStore::GetPendingSafeSearchCheckMediaFeedItems() {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
 
   if (!initialization_successful_ || !feed_items_table_)
@@ -703,7 +630,7 @@
   return feed_items_table_->GetPendingSafeSearchCheckItems();
 }
 
-void MediaHistoryStoreInternal::StoreMediaFeedItemSafeSearchResults(
+void MediaHistoryStore::StoreMediaFeedItemSafeSearchResults(
     std::map<int64_t, media_feeds::mojom::SafeSearchResult> results) {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
   if (!initialization_successful_)
@@ -727,213 +654,4 @@
   DB()->CommitTransaction();
 }
 
-const char MediaHistoryStore::kInitResultHistogramName[] =
-    "Media.History.Init.Result";
-
-const char MediaHistoryStore::kPlaybackWriteResultHistogramName[] =
-    "Media.History.Playback.WriteResult";
-
-const char MediaHistoryStore::kSessionWriteResultHistogramName[] =
-    "Media.History.Session.WriteResult";
-
-const char MediaHistoryStore::kDatabaseSizeKbHistogramName[] =
-    "Media.History.DatabaseSize";
-
-MediaHistoryStore::MediaHistoryStore(
-    Profile* profile,
-    scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner)
-    : db_(new MediaHistoryStoreInternal(profile, db_task_runner)),
-      profile_(profile) {
-  db_task_runner->PostTask(
-      FROM_HERE, base::BindOnce(&MediaHistoryStoreInternal::Initialize, db_));
-}
-
-MediaHistoryStore::~MediaHistoryStore() {}
-
-void MediaHistoryStore::SavePlayback(
-    const content::MediaPlayerWatchTime& watch_time) {
-  if (!db_->initialization_successful_)
-    return;
-
-  db_->db_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&MediaHistoryStoreInternal::SavePlayback, db_,
-                                watch_time));
-}
-
-void MediaHistoryStore::GetPendingSafeSearchCheckMediaFeedItems(
-    base::OnceCallback<
-        void(MediaHistoryKeyedService::PendingSafeSearchCheckList)> callback) {
-  if (!db_->initialization_successful_) {
-    return std::move(callback).Run(
-        MediaHistoryKeyedService::PendingSafeSearchCheckList());
-  }
-
-  base::PostTaskAndReplyWithResult(
-      db_->db_task_runner_.get(), FROM_HERE,
-      base::BindOnce(
-          &MediaHistoryStoreInternal::GetPendingSafeSearchCheckMediaFeedItems,
-          db_),
-      std::move(callback));
-}
-
-void MediaHistoryStore::StoreMediaFeedItemSafeSearchResults(
-    std::map<int64_t, media_feeds::mojom::SafeSearchResult> results) {
-  if (!db_->initialization_successful_)
-    return;
-
-  db_->db_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          &MediaHistoryStoreInternal::StoreMediaFeedItemSafeSearchResults, db_,
-          results));
-}
-
-scoped_refptr<base::UpdateableSequencedTaskRunner>
-MediaHistoryStore::GetDBTaskRunnerForTest() {
-  return db_->db_task_runner_;
-}
-
-void MediaHistoryStore::EraseDatabaseAndCreateNew() {
-  auto db_task_runner = db_->db_task_runner_;
-  auto db_path = db_->db_path_;
-
-  db_task_runner->PostTask(
-      FROM_HERE, base::BindOnce(&MediaHistoryStoreInternal::RazeAndClose, db_));
-
-  // Create a new internal store.
-  db_ = new MediaHistoryStoreInternal(profile_, db_task_runner);
-  db_task_runner->PostTask(
-      FROM_HERE, base::BindOnce(&MediaHistoryStoreInternal::Initialize, db_));
-}
-
-void MediaHistoryStore::GetMediaHistoryStats(
-    base::OnceCallback<void(mojom::MediaHistoryStatsPtr)> callback) {
-  if (!db_->initialization_successful_)
-    return std::move(callback).Run(mojom::MediaHistoryStats::New());
-
-  base::PostTaskAndReplyWithResult(
-      db_->db_task_runner_.get(), FROM_HERE,
-      base::BindOnce(&MediaHistoryStoreInternal::GetMediaHistoryStats, db_),
-      std::move(callback));
-}
-
-void MediaHistoryStore::GetOriginRowsForDebug(
-    base::OnceCallback<void(std::vector<mojom::MediaHistoryOriginRowPtr>)>
-        callback) {
-  if (!db_->initialization_successful_) {
-    return std::move(callback).Run(
-        std::vector<mojom::MediaHistoryOriginRowPtr>());
-  }
-
-  base::PostTaskAndReplyWithResult(
-      db_->db_task_runner_.get(), FROM_HERE,
-      base::BindOnce(&MediaHistoryStoreInternal::GetOriginRowsForDebug, db_),
-      std::move(callback));
-}
-
-void MediaHistoryStore::GetMediaHistoryPlaybackRowsForDebug(
-    base::OnceCallback<void(std::vector<mojom::MediaHistoryPlaybackRowPtr>)>
-        callback) {
-  base::PostTaskAndReplyWithResult(
-      db_->db_task_runner_.get(), FROM_HERE,
-      base::BindOnce(
-          &MediaHistoryStoreInternal::GetMediaHistoryPlaybackRowsForDebug, db_),
-      std::move(callback));
-}
-
-void MediaHistoryStore::GetMediaFeedsForDebug(
-    base::OnceCallback<void(std::vector<media_feeds::mojom::MediaFeedPtr>)>
-        callback) {
-  base::PostTaskAndReplyWithResult(
-      db_->db_task_runner_.get(), FROM_HERE,
-      base::BindOnce(&MediaHistoryStoreInternal::GetMediaFeedsForDebug, db_),
-      std::move(callback));
-}
-
-void MediaHistoryStore::SavePlaybackSession(
-    const GURL& url,
-    const media_session::MediaMetadata& metadata,
-    const base::Optional<media_session::MediaPosition>& position,
-    const std::vector<media_session::MediaImage>& artwork) {
-  if (!db_->initialization_successful_)
-    return;
-
-  db_->db_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&MediaHistoryStoreInternal::SavePlaybackSession,
-                                db_, url, metadata, position, artwork));
-}
-
-void MediaHistoryStore::GetPlaybackSessions(
-    base::Optional<unsigned int> num_sessions,
-    base::Optional<GetPlaybackSessionsFilter> filter,
-    base::OnceCallback<
-        void(std::vector<mojom::MediaHistoryPlaybackSessionRowPtr>)> callback) {
-  base::PostTaskAndReplyWithResult(
-      db_->db_task_runner_.get(), FROM_HERE,
-      base::BindOnce(&MediaHistoryStoreInternal::GetPlaybackSessions, db_,
-                     num_sessions, std::move(filter)),
-      std::move(callback));
-}
-
-void MediaHistoryStore::DeleteAllOriginData(
-    const std::set<url::Origin>& origins) {
-  db_->db_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&MediaHistoryStoreInternal::DeleteAllOriginData,
-                                db_, origins));
-}
-
-void MediaHistoryStore::DeleteAllURLData(const std::set<GURL>& urls) {
-  db_->db_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&MediaHistoryStoreInternal::DeleteAllURLData, db_, urls));
-}
-
-void MediaHistoryStore::GetURLsInTableForTest(
-    const std::string& table,
-    base::OnceCallback<void(std::set<GURL>)> callback) {
-  base::PostTaskAndReplyWithResult(
-      db_->db_task_runner_.get(), FROM_HERE,
-      base::BindOnce(&MediaHistoryStoreInternal::GetURLsInTableForTest, db_,
-                     table),
-      std::move(callback));
-}
-
-void MediaHistoryStore::DiscoverMediaFeed(const GURL& url) {
-  CHECK(url.SchemeIsCryptographic());
-
-  db_->db_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&MediaHistoryStoreInternal::DiscoverMediaFeed, db_, url));
-}
-
-void MediaHistoryStore::PostTaskToDBForTest(base::OnceClosure callback) {
-  db_->db_task_runner_->PostTaskAndReply(FROM_HERE, base::DoNothing(),
-                                         std::move(callback));
-}
-
-void MediaHistoryStore::StoreMediaFeedFetchResult(
-    const int64_t feed_id,
-    std::vector<media_feeds::mojom::MediaFeedItemPtr> items,
-    const media_feeds::mojom::FetchResult result,
-    const bool was_fetched_from_cache,
-    const std::vector<media_session::MediaImage>& logos,
-    const std::string& display_name) {
-  db_->db_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&MediaHistoryStoreInternal::StoreMediaFeedFetchResult, db_,
-                     feed_id, std::move(items), result, was_fetched_from_cache,
-                     logos, display_name));
-}
-
-void MediaHistoryStore::GetItemsForMediaFeedForDebug(
-    const int64_t feed_id,
-    base::OnceCallback<void(std::vector<media_feeds::mojom::MediaFeedItemPtr>)>
-        callback) {
-  base::PostTaskAndReplyWithResult(
-      db_->db_task_runner_.get(), FROM_HERE,
-      base::BindOnce(&MediaHistoryStoreInternal::GetItemsForMediaFeedForDebug,
-                     db_, feed_id),
-      std::move(callback));
-}
-
 }  // namespace media_history
diff --git a/chrome/browser/media/history/media_history_store.h b/chrome/browser/media/history/media_history_store.h
index 33b22285..f0452b6 100644
--- a/chrome/browser/media/history/media_history_store.h
+++ b/chrome/browser/media/history/media_history_store.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_STORE_H_
 #define CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_STORE_H_
 
-#include <memory>
 #include <set>
 #include <vector>
 
@@ -16,13 +15,9 @@
 #include "base/updateable_sequenced_task_runner.h"
 #include "chrome/browser/media/feeds/media_feeds_store.mojom.h"
 #include "chrome/browser/media/history/media_history_keyed_service.h"
-#include "chrome/browser/media/history/media_history_origin_table.h"
-#include "chrome/browser/media/history/media_history_playback_table.h"
 #include "chrome/browser/media/history/media_history_store.mojom.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/media_player_watch_time.h"
-#include "services/media_session/public/cpp/media_metadata.h"
-#include "sql/database.h"
 #include "sql/init_status.h"
 #include "sql/meta_table.h"
 
@@ -42,14 +37,22 @@
 
 namespace media_history {
 
-class MediaHistoryStoreInternal;
+class MediaHistoryOriginTable;
+class MediaHistoryPlaybackTable;
+class MediaHistorySessionTable;
+class MediaHistorySessionImagesTable;
+class MediaHistoryImagesTable;
+class MediaHistoryFeedsTable;
+class MediaHistoryFeedItemsTable;
 
-class MediaHistoryStore {
+// Refcounted as it is created, initialized and destroyed on a different thread
+// from the DB sequence provided to the constructor of this class that is
+// required for all methods performing database access.
+class MediaHistoryStore : public base::RefCountedThreadSafe<MediaHistoryStore> {
  public:
   MediaHistoryStore(
       Profile* profile,
       scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
-  ~MediaHistoryStore();
   MediaHistoryStore(const MediaHistoryStore& t) = delete;
   MediaHistoryStore& operator=(const MediaHistoryStore&) = delete;
 
@@ -100,48 +103,46 @@
  protected:
   friend class MediaHistoryKeyedService;
 
-  // Saves a playback from a single player in the media history store.
+  // Opens the database file from the |db_path|. Separated from the
+  // constructor to ease construction/destruction of this object on one thread
+  // and database access on the DB sequence of |db_task_runner_|.
+  void Initialize();
+
+  sql::InitStatus CreateOrUpgradeIfNeeded();
+  sql::InitStatus InitializeTables();
+  sql::Database* DB();
+
+  // Returns a flag indicating whether the origin id was created successfully.
+  bool CreateOriginId(const url::Origin& origin);
+
   void SavePlayback(const content::MediaPlayerWatchTime& watch_time);
 
-  void GetMediaHistoryStats(
-      base::OnceCallback<void(mojom::MediaHistoryStatsPtr)> callback);
+  mojom::MediaHistoryStatsPtr GetMediaHistoryStats();
+  int GetTableRowCount(const std::string& table_name);
 
-  // Returns all the rows in the origin table. This should only be used for
-  // debugging because it is very slow.
-  void GetOriginRowsForDebug(
-      base::OnceCallback<void(std::vector<mojom::MediaHistoryOriginRowPtr>)>
-          callback);
+  std::vector<mojom::MediaHistoryOriginRowPtr> GetOriginRowsForDebug();
 
-  // Returns all the rows in the playback table. This is only used for
-  // debugging because it loads all rows in the table.
-  void GetMediaHistoryPlaybackRowsForDebug(
-      base::OnceCallback<void(std::vector<mojom::MediaHistoryPlaybackRowPtr>)>
-          callback);
+  std::vector<mojom::MediaHistoryPlaybackRowPtr>
+  GetMediaHistoryPlaybackRowsForDebug();
 
-  // Returns all the rows in the media feeds table.  This is only used for
-  // debugging because it loads all rows in the table.
-  void GetMediaFeedsForDebug(
-      base::OnceCallback<void(std::vector<media_feeds::mojom::MediaFeedPtr>)>
-          callback);
+  std::vector<media_feeds::mojom::MediaFeedPtr> GetMediaFeedsForDebug();
 
-  // Gets the playback sessions from the media history store. The results will
-  // be ordered by most recent first and be limited to the first |num_sessions|.
-  // For each session it calls |filter| and if that returns |true| then that
-  // session will be included in the results.
-  void GetPlaybackSessions(
-      base::Optional<unsigned int> num_sessions,
-      base::Optional<GetPlaybackSessionsFilter> filter,
-      base::OnceCallback<void(
-          std::vector<mojom::MediaHistoryPlaybackSessionRowPtr>)> callback);
-
-  // Saves a playback session in the media history store.
   void SavePlaybackSession(
       const GURL& url,
       const media_session::MediaMetadata& metadata,
       const base::Optional<media_session::MediaPosition>& position,
       const std::vector<media_session::MediaImage>& artwork);
 
-  // Saves a newly discovered media feed in the media history store.
+  std::vector<mojom::MediaHistoryPlaybackSessionRowPtr> GetPlaybackSessions(
+      base::Optional<unsigned int> num_sessions,
+      base::Optional<MediaHistoryStore::GetPlaybackSessionsFilter> filter);
+
+  void RazeAndClose();
+  void DeleteAllOriginData(const std::set<url::Origin>& origins);
+  void DeleteAllURLData(const std::set<GURL>& urls);
+
+  std::set<GURL> GetURLsInTableForTest(const std::string& table);
+
   void DiscoverMediaFeed(const GURL& url);
 
   void StoreMediaFeedFetchResult(
@@ -152,33 +153,32 @@
       const std::vector<media_session::MediaImage>& logos,
       const std::string& display_name);
 
-  // Gets all the feed items for |feed_id|.
-  void GetItemsForMediaFeedForDebug(
-      const int64_t feed_id,
-      base::OnceCallback<
-          void(std::vector<media_feeds::mojom::MediaFeedItemPtr>)> callback);
+  std::vector<media_feeds::mojom::MediaFeedItemPtr>
+  GetItemsForMediaFeedForDebug(const int64_t feed_id);
 
-  void GetPendingSafeSearchCheckMediaFeedItems(
-      base::OnceCallback<
-          void(MediaHistoryKeyedService::PendingSafeSearchCheckList)> callback);
+  MediaHistoryKeyedService::PendingSafeSearchCheckList
+  GetPendingSafeSearchCheckMediaFeedItems();
 
   void StoreMediaFeedItemSafeSearchResults(
       std::map<int64_t, media_feeds::mojom::SafeSearchResult> results);
 
-  scoped_refptr<base::UpdateableSequencedTaskRunner> GetDBTaskRunnerForTest();
-
-  void GetURLsInTableForTest(const std::string& table,
-                             base::OnceCallback<void(std::set<GURL>)> callback);
-
-  void PostTaskToDBForTest(base::OnceClosure callback);
-  void EraseDatabaseAndCreateNew();
-  void DeleteAllOriginData(const std::set<url::Origin>& origins);
-  void DeleteAllURLData(const std::set<GURL>& urls);
-
  private:
-  scoped_refptr<MediaHistoryStoreInternal> db_;
+  friend class base::RefCountedThreadSafe<MediaHistoryStore>;
 
-  Profile* const profile_;
+  ~MediaHistoryStore();
+
+  scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner_;
+  const base::FilePath db_path_;
+  std::unique_ptr<sql::Database> db_;
+  sql::MetaTable meta_table_;
+  scoped_refptr<MediaHistoryOriginTable> origin_table_;
+  scoped_refptr<MediaHistoryPlaybackTable> playback_table_;
+  scoped_refptr<MediaHistorySessionTable> session_table_;
+  scoped_refptr<MediaHistorySessionImagesTable> session_images_table_;
+  scoped_refptr<MediaHistoryImagesTable> images_table_;
+  scoped_refptr<MediaHistoryFeedsTable> feeds_table_;
+  scoped_refptr<MediaHistoryFeedItemsTable> feed_items_table_;
+  bool initialization_successful_;
 };
 
 }  // namespace media_history
diff --git a/chrome/browser/media/history/media_history_store_unittest.cc b/chrome/browser/media/history/media_history_store_unittest.cc
index ea8da7a..2bd1857 100644
--- a/chrome/browser/media/history/media_history_store_unittest.cc
+++ b/chrome/browser/media/history/media_history_store_unittest.cc
@@ -22,7 +22,8 @@
 #include "chrome/browser/media/history/media_history_feed_items_table.h"
 #include "chrome/browser/media/history/media_history_feeds_table.h"
 #include "chrome/browser/media/history/media_history_images_table.h"
-#include "chrome/browser/media/history/media_history_keyed_service.h"
+#include "chrome/browser/media/history/media_history_origin_table.h"
+#include "chrome/browser/media/history/media_history_playback_table.h"
 #include "chrome/browser/media/history/media_history_session_images_table.h"
 #include "chrome/browser/media/history/media_history_session_table.h"
 #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/net/websocket_browsertest.cc b/chrome/browser/net/websocket_browsertest.cc
index 03853a6..e218335 100644
--- a/chrome/browser/net/websocket_browsertest.cc
+++ b/chrome/browser/net/websocket_browsertest.cc
@@ -2,11 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <string>
+#include <stdint.h>
 
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
 #include "base/macros.h"
+#include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/login/login_handler.h"
@@ -18,12 +28,26 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_source.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "net/base/network_isolation_key.h"
+#include "net/cookies/site_for_cookies.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
 #include "net/test/test_data_directory.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/public/mojom/websocket.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
+#include "url/origin.h"
 
 namespace {
 
@@ -354,4 +378,171 @@
   EXPECT_EQ("PASS", WaitAndGetTitle());
 }
 
+// An implementation of WebSocketClient that expects the mojo connection to be
+// disconnected due to invalid UTF-8.
+class ExpectInvalidUtf8Client : public network::mojom::WebSocketClient {
+ public:
+  ExpectInvalidUtf8Client(base::OnceClosure success_closure,
+                          base::RepeatingClosure fail_closure)
+      : success_closure_(std::move(success_closure)),
+        fail_closure_(fail_closure) {}
+
+  ~ExpectInvalidUtf8Client() override = default;
+
+  ExpectInvalidUtf8Client(const ExpectInvalidUtf8Client&) = delete;
+  ExpectInvalidUtf8Client& operator=(ExpectInvalidUtf8Client&) = delete;
+
+  void Bind(mojo::PendingReceiver<network::mojom::WebSocketClient> receiver) {
+    client_receiver_.Bind(std::move(receiver));
+    // This use of base::Unretained is safe because the disconnect handler will
+    // not be called after |client_receiver_| is destroyed.
+    client_receiver_.set_disconnect_with_reason_handler(base::BindRepeating(
+        &ExpectInvalidUtf8Client::OnDisconnect, base::Unretained(this)));
+  }
+
+  // Implementation of WebSocketClient
+  void OnDataFrame(bool fin,
+                   network::mojom::WebSocketMessageType,
+                   uint64_t data_length) override {
+    NOTREACHED();
+  }
+
+  void AddSendFlowControlQuota(int64_t quota) override {}
+
+  void OnDropChannel(bool was_clean,
+                     uint16_t code,
+                     const std::string& reason) override {
+    NOTREACHED();
+  }
+
+  void OnClosingHandshake() override { NOTREACHED(); }
+
+ private:
+  void OnDisconnect(uint32_t reason, const std::string& message) {
+    if (reason == network::mojom::WebSocket::kInternalFailure &&
+        message == "Browser sent a text frame containing invalid UTF-8") {
+      std::move(success_closure_).Run();
+    } else {
+      ADD_FAILURE() << "Unexpected disconnect: reason=" << reason
+                    << " message=\"" << message << '"';
+      fail_closure_.Run();
+    }
+  }
+
+  base::OnceClosure success_closure_;
+  const base::RepeatingClosure fail_closure_;
+
+  mojo::Receiver<network::mojom::WebSocketClient> client_receiver_{this};
+};
+
+// An implementation of WebSocketHandshakeClient that sends a text message
+// containing invalid UTF-8 when the connection is established.
+class InvalidUtf8HandshakeClient
+    : public network::mojom::WebSocketHandshakeClient {
+ public:
+  InvalidUtf8HandshakeClient(std::unique_ptr<ExpectInvalidUtf8Client> client,
+                             base::RepeatingClosure fail_closure)
+      : client_(std::move(client)), fail_closure_(fail_closure) {}
+  ~InvalidUtf8HandshakeClient() override = default;
+
+  InvalidUtf8HandshakeClient(const InvalidUtf8HandshakeClient&) = delete;
+  InvalidUtf8HandshakeClient& operator=(const InvalidUtf8HandshakeClient&) =
+      delete;
+
+  mojo::PendingRemote<network::mojom::WebSocketHandshakeClient> Bind() {
+    auto pending_remote = handshake_client_receiver_.BindNewPipeAndPassRemote();
+    // This use of base::Unretained is safe because the disconnect handler will
+    // not be called after |handshake_client_receiver_| is destroyed.
+    handshake_client_receiver_.set_disconnect_handler(
+        base::BindOnce(&InvalidUtf8HandshakeClient::FailIfNotConnected,
+                       base::Unretained(this)));
+    return pending_remote;
+  }
+
+  // Implementation of WebSocketHandshakeClient
+  void OnOpeningHandshakeStarted(
+      network::mojom::WebSocketHandshakeRequestPtr) override {}
+
+  void OnConnectionEstablished(
+      mojo::PendingRemote<network::mojom::WebSocket> websocket,
+      mojo::PendingReceiver<network::mojom::WebSocketClient> client_receiver,
+      network::mojom::WebSocketHandshakeResponsePtr,
+      mojo::ScopedDataPipeConsumerHandle readable,
+      mojo::ScopedDataPipeProducerHandle writable) override {
+    client_->Bind(std::move(client_receiver));
+    websocket_.Bind(std::move(websocket));
+
+    // Invalid UTF-8.
+    static const uint32_t message[] = {0xff};
+    uint32_t size = static_cast<uint32_t>(sizeof(message));
+
+    websocket_->SendMessage(network::mojom::WebSocketMessageType::TEXT, size);
+
+    EXPECT_EQ(writable->WriteData(message, &size, MOJO_WRITE_DATA_FLAG_NONE),
+              MOJO_RESULT_OK);
+    EXPECT_EQ(size, sizeof(message));
+
+    connected_ = true;
+  }
+
+ private:
+  void FailIfNotConnected() {
+    if (!connected_) {
+      fail_closure_.Run();
+    }
+  }
+
+  const std::unique_ptr<ExpectInvalidUtf8Client> client_;
+  const base::RepeatingClosure fail_closure_;
+  bool connected_ = false;
+
+  mojo::Receiver<network::mojom::WebSocketHandshakeClient>
+      handshake_client_receiver_{this};
+  mojo::Remote<network::mojom::WebSocket> websocket_;
+};
+
+IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, SendBadUtf8) {
+  ASSERT_TRUE(ws_server_.Start());
+
+  base::RunLoop run_loop;
+
+  bool failed = false;
+
+  // This is a repeating closure for convenience so that we can use it in two
+  // places.
+  const base::RepeatingClosure fail_closure = base::BindLambdaForTesting([&]() {
+    failed = true;
+    run_loop.Quit();
+  });
+
+  auto client = std::make_unique<ExpectInvalidUtf8Client>(
+      run_loop.QuitClosure(), fail_closure);
+
+  content::RenderFrameHost* const frame =
+      browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
+  content::RenderProcessHost* const process = frame->GetProcess();
+
+  const GURL url = ws_server_.GetURL("close");
+  const std::vector<std::string> requested_protocols;
+  const net::SiteForCookies site_for_cookies;
+  const net::NetworkIsolationKey network_isolation_key;
+  std::vector<network::mojom::HttpHeaderPtr> additional_headers;
+  const url::Origin origin;
+  auto handshake_client = std::make_unique<InvalidUtf8HandshakeClient>(
+      std::move(client), fail_closure);
+  mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
+      handshake_client_remote = handshake_client->Bind();
+
+  process->GetStoragePartition()->GetNetworkContext()->CreateWebSocket(
+      url, requested_protocols, site_for_cookies, network_isolation_key,
+      std::move(additional_headers), process->GetID(), frame->GetRoutingID(),
+      origin, network::mojom::kWebSocketOptionNone,
+      std::move(handshake_client_remote), mojo::NullRemote(),
+      mojo::NullRemote());
+
+  run_loop.Run();
+
+  EXPECT_FALSE(failed);
+}
+
 }  // namespace
diff --git a/chrome/browser/offline_pages/android/prefetch_test_bridge.cc b/chrome/browser/offline_pages/android/prefetch_test_bridge.cc
index 7f7fcccd..4549b073 100644
--- a/chrome/browser/offline_pages/android/prefetch_test_bridge.cc
+++ b/chrome/browser/offline_pages/android/prefetch_test_bridge.cc
@@ -63,7 +63,8 @@
   std::string image_data;
   base::android::JavaByteArrayToString(env, j_image_data, &image_data);
 
-  cache->SaveImage(url, image_data, false /* needs_transcoding */);
+  cache->SaveImage(url, image_data, false /* needs_transcoding */,
+                   base::nullopt /* expiration_interval */);
 }
 
 JNI_EXPORT void JNI_PrefetchTestBridge_AddCandidatePrefetchURL(
diff --git a/chrome/browser/resources/new_tab_page/logo.html b/chrome/browser/resources/new_tab_page/logo.html
index 981b763a..28e7e90 100644
--- a/chrome/browser/resources/new_tab_page/logo.html
+++ b/chrome/browser/resources/new_tab_page/logo.html
@@ -26,10 +26,15 @@
     cursor: pointer;
     display: grid;
     height: 230px;
+    outline: none;
     position: relative;
     width: 500px;
   }
 
+  :host-context(.focus-outline-visible) #imageContainer:focus {
+    box-shadow: 0 0 0 2px rgba(var(--google-blue-600-rgb), .4);
+  }
+
   #imageContainer > * {
     grid-column-start: 1;
     grid-row-start: 1;
@@ -77,7 +82,7 @@
   </div>
   <div id="doodle">
     <div id="imageContainer" hidden="[[!doodle_.content.imageDoodle]]"
-        on-click="onImageClick_">
+        tabindex="1" on-click="onImageClick_" on-keydown="onImageKeydown_">
       <!-- The static image is always visible and the animated image is stacked
            on top of the static image so that there is no flicker when starting
            the animation. -->
diff --git a/chrome/browser/resources/new_tab_page/logo.js b/chrome/browser/resources/new_tab_page/logo.js
index 386911e8..7f4d003a 100644
--- a/chrome/browser/resources/new_tab_page/logo.js
+++ b/chrome/browser/resources/new_tab_page/logo.js
@@ -166,6 +166,16 @@
   }
 
   /**
+   * @param {!Event} e
+   * @private
+   */
+  onImageKeydown_(e) {
+    if ([' ', 'Enter'].includes(e.key)) {
+      this.onImageClick_();
+    }
+  }
+
+  /**
    * @return {string}
    * @private
    */
diff --git a/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.js b/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.js
index b1c5e5ee..45c02c5 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/device_page_browser_proxy.js
@@ -47,8 +47,12 @@
 
   /**
    * @typedef {{
-   *   idleBehavior: settings.IdleBehavior,
-   *   idleControlled: boolean,
+   *   possibleAcIdleBehaviors: !Array<settings.IdleBehavior>,
+   *   possibleBatteryIdleBehaviors: !Array<settings.IdleBehavior>,
+   *   acIdleManaged: boolean,
+   *   batteryIdleManaged: boolean,
+   *   currentAcIdleBehavior: settings.IdleBehavior,
+   *   currentBatteryIdleBehavior: settings.IdleBehavior,
    *   lidClosedBehavior: settings.LidClosedBehavior,
    *   lidClosedControlled: boolean,
    *   hasLid: boolean,
@@ -115,8 +119,10 @@
     /**
      * Sets the idle power management behavior.
      * @param {settings.IdleBehavior} behavior Idle behavior.
+     * @param {boolean} whenOnAc If true sets AC idle behavior. Otherwise sets
+     *     battery idle behavior.
      */
-    setIdleBehavior(behavior) {}
+    setIdleBehavior(behavior, whenOnAc) {}
 
     /**
      * Sets the lid-closed power management behavior.
@@ -167,6 +173,14 @@
      * @param {function(Array<!settings.ExternalStorage>):void} callback
      */
     setExternalStoragesUpdatedCallback(callback) {}
+
+    /**
+     * Sets |id| of display to render identification highlight on. Invalid |id|
+     * turns identification highlight off. Handles any invalid input string as
+     * invalid id.
+     * @param {string} id Display id of selected display.
+     */
+    highlightDisplay(id) {}
   }
 
   /**
@@ -214,8 +228,8 @@
     }
 
     /** @override */
-    setIdleBehavior(behavior) {
-      chrome.send('setIdleBehavior', [behavior]);
+    setIdleBehavior(behavior, whenOnAc) {
+      chrome.send('setIdleBehavior', [behavior, whenOnAc]);
     }
 
     /** @override */
@@ -257,6 +271,11 @@
     setExternalStoragesUpdatedCallback(callback) {
       cr.addWebUIListener('onExternalStoragesUpdated', callback);
     }
+
+    /** @override */
+    highlightDisplay(id) {
+      chrome.send('highlightDisplay', [id]);
+    }
   }
 
   cr.addSingletonGetter(DevicePageBrowserProxyImpl);
diff --git a/chrome/browser/resources/settings/chromeos/device_page/power.html b/chrome/browser/resources/settings/chromeos/device_page/power.html
index 9d7a0ca..7d96cfb 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/power.html
+++ b/chrome/browser/resources/settings/chromeos/device_page/power.html
@@ -12,7 +12,27 @@
 
 <dom-module id="settings-power">
   <template>
-    <style include="settings-shared md-select"></style>
+    <style include="settings-shared md-select">
+      .indented {
+        align-self: stretch;
+        margin-inline-start: var(--cr-section-indent-padding);
+        padding: 0;
+      }
+
+      #powerIdleLabel {
+        align-self: stretch;
+        padding-top: var(--cr-section-padding);
+      }
+
+      .subsection {
+        @apply --cr-section;
+        flex-direction: column;
+      }
+
+      .subsection.first {
+        border-top: none;
+      }
+    </style>
     <div id="powerSourceRow" class="settings-box first two-line"
         hidden$="[[!batteryStatus_.present]]">
       <div class="start" id="powerSourceLabelDiv">
@@ -38,29 +58,58 @@
       </div>
     </div>
 
-    <div class$="settings-box [[getFirst_(batteryStatus_.present)]]">
-      <div class="start" aria-hidden="true">$i18n{powerIdleLabel}</div>
-      <template is="dom-if" if="[[idleControlled_]]" restamp>
-        <cr-policy-indicator id="idleControlledIndicator"
-            indicator-type="devicePolicy"
-            icon-aria-label="$i18n{powerIdleLabel}">
-        </cr-policy-indicator>
-      </template>
-      <select id="idleSelect" class="md-select"
-          on-change="onIdleSelectChange_" disabled="[[idleControlled_]]"
-          aria-label="$i18n{powerIdleLabel}">
-        <template is="dom-repeat" items="[[idleOptions_]]">
-          <option value="[[item.value]]">[[item.name]]</option>
+    <div class$="subsection [[getFirst_(batteryStatus_.present)]]">
+      <div id="powerIdleLabel" aria-hidden="true">$i18n{powerIdleLabel}</div>
+      <div class="settings-box indented first">
+        <div class="start" aria-hidden="true">
+          $i18n{powerIdleWhileChargingLabel}
+        </div>
+        <template is="dom-if" if="[[acIdleManaged_]]" restamp>
+          <cr-policy-indicator id="acIdleManagedIndicator"
+              indicator-type="devicePolicy"
+              icon-aria-label="$i18n{powerIdleWhileChargingAriaLabel}">
+          </cr-policy-indicator>
         </template>
-      </select>
+        <select id="acIdleSelect" class="md-select"
+            on-change="onAcIdleSelectChange_"
+            disabled="[[shouldAcIdleSelectBeDisabled_]]"
+            aria-label="$i18n{powerIdleWhileChargingAriaLabel}"
+            value="{{currAcIdleBehavior_}}">
+          <template is="dom-repeat" items="[[acIdleOptions_]]">
+            <option value="[[item.value]]">[[item.name]]</option>
+          </template>
+        </select>
+      </div>
+
+      <template is="dom-if" if="[[batteryStatus_.present]]" restamp>
+        <div id="batteryIdleSettingBox" class="settings-box indented">
+          <div class="start" aria-hidden="true">
+            $i18n{powerIdleWhileOnBatteryLabel}
+          </div>
+          <template is="dom-if" if="[[batteryIdleManaged_]]" restamp>
+            <cr-policy-indicator id="batteryIdleManagedIndicator"
+                indicator-type="devicePolicy"
+                icon-aria-label="$i18n{powerIdleWhileOnBatteryAriaLabel}">
+            </cr-policy-indicator>
+          </template>
+          <select id="batteryIdleSelect" class="md-select"
+              on-change="onBatteryIdleSelectChange_"
+              disabled="[[shouldBatteryIdleSelectBeDisabled_]]"
+              aria-label="$i18n{powerIdleWhileOnBatteryAriaLabel}"
+              value="{{currBatteryIdleBehavior_}}">
+            <template is="dom-repeat" items="[[batteryIdleOptions_]]">
+              <option value="[[item.value]]">[[item.name]]</option>
+            </template>
+          </select>
+        </div>
+      </template>
     </div>
 
-    <settings-toggle-button class="continuation" hidden$="[[!hasLid_]]"
-        id="lidClosedToggle"
-        pref="[[lidClosedPref_]]" label="[[lidClosedLabel_]]"
-        on-settings-boolean-control-change="onLidClosedToggleChange_"
-        no-set-pref>
+
+    <settings-toggle-button hidden$="[[!hasLid_]]" id="lidClosedToggle"
+      pref="[[lidClosedPref_]]" label="[[lidClosedLabel_]]"
+      on-settings-boolean-control-change="onLidClosedToggleChange_" no-set-pref>
     </settings-toggle-button>
   </template>
   <script src="power.js"></script>
-</dom-module>
+</dom-module>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/device_page/power.js b/chrome/browser/resources/settings/chromeos/device_page/power.js
index e9f240d9..af1ef497 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/power.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/power.js
@@ -27,8 +27,14 @@
     /** @private {boolean} Whether a low-power (USB) charger is being used. */
     lowPowerCharger_: Boolean,
 
-    /** @private {boolean} Whether the idle behavior is controlled by policy. */
-    idleControlled_: Boolean,
+    /** @private {boolean} Whether the AC idle behavior is managed by policy. */
+    acIdleManaged_: Boolean,
+
+    /**
+     * @private {boolean} Whether the battery idle behavior is managed by
+     *     policy.
+     */
+    batteryIdleManaged_: Boolean,
 
     /** @private {string} Text for label describing the lid-closed behavior. */
     lidClosedLabel_: String,
@@ -36,6 +42,12 @@
     /** @private {boolean} Whether the system possesses a lid. */
     hasLid_: Boolean,
 
+    /** @private {number} Current AC idle behavior */
+    currAcIdleBehavior_: Number,
+
+    /** @private {number} Current battery idle behavior */
+    currBatteryIdleBehavior_: Number,
+
     /**
      * List of available dual-role power sources, if enablePowerSettings is on.
      * @private {!Array<!settings.PowerSource>|undefined}
@@ -65,10 +77,32 @@
       computed: 'computePowerSourceName_(powerSources_, lowPowerCharger_)',
     },
 
-    /** @private */
-    idleOptions_: {
+    /** @private {Array<!{value: settings.IdleBehavior, name: string}>} */
+    acIdleOptions_: {
       type: Array,
-      computed: 'computeIdleOptions_(idleControlled_)',
+      value() {
+        return [];
+      },
+    },
+
+    /** @private {Array<!{value: settings.IdleBehavior, name: string}>} */
+    batteryIdleOptions_: {
+      type: Array,
+      value() {
+        return [];
+      },
+    },
+
+    /** @private {boolean} */
+    shouldAcIdleSelectBeDisabled_: {
+      type: Boolean,
+      computed: 'hasSingleOption_(acIdleOptions_)',
+    },
+
+    /** @private {boolean} */
+    shouldBatteryIdleSelectBeDisabled_: {
+      type: Boolean,
+      computed: 'hasSingleOption_(batteryIdleOptions_)',
     },
 
     /** @private {!chrome.settingsPrivate.PrefObject} */
@@ -80,6 +114,14 @@
     },
   },
 
+  /** @private {?settings.DevicePageBrowserProxy} */
+  browserProxy_: null,
+
+  /** @override */
+  created() {
+    this.browserProxy_ = settings.DevicePageBrowserProxyImpl.getInstance();
+  },
+
   /** @override */
   ready() {
     // enablePowerSettings comes from loadTimeData, so it will always be set
@@ -95,13 +137,12 @@
         'battery-status-changed', this.set.bind(this, 'batteryStatus_'));
     this.addWebUIListener(
         'power-sources-changed', this.powerSourcesChanged_.bind(this));
-    settings.DevicePageBrowserProxyImpl.getInstance().updatePowerStatus();
+    this.browserProxy_.updatePowerStatus();
 
     this.addWebUIListener(
         'power-management-settings-changed',
         this.powerManagementSettingsChanged_.bind(this));
-    settings.DevicePageBrowserProxyImpl.getInstance()
-        .requestPowerManagementSettings();
+    this.browserProxy_.requestPowerManagementSettings();
   },
 
   /**
@@ -146,47 +187,34 @@
     return '';
   },
 
-  /**
-   * @param {boolean} idleControlled
-   * @return {!Array<!{value: settings.IdleBehavior, name: string}>} Options to
-   *     display in idle-behavior select.
-   * @private
-   */
-  computeIdleOptions_(idleControlled) {
-    const options = [
-      {
-        value: settings.IdleBehavior.DISPLAY_OFF_SLEEP,
-        name: loadTimeData.getString('powerIdleDisplayOffSleep'),
-      },
-      {
-        value: settings.IdleBehavior.DISPLAY_OFF,
-        name: loadTimeData.getString('powerIdleDisplayOff'),
-      },
-      {
-        value: settings.IdleBehavior.DISPLAY_ON,
-        name: loadTimeData.getString('powerIdleDisplayOn'),
-      },
-    ];
-    if (idleControlled) {
-      options.push({
-        value: settings.IdleBehavior.OTHER,
-        name: loadTimeData.getString('powerIdleOther'),
-      });
-    }
-    return options;
-  },
-
   /** @private */
   onPowerSourceChange_() {
-    settings.DevicePageBrowserProxyImpl.getInstance().setPowerSource(
-        this.$.powerSource.value);
+    this.browserProxy_.setPowerSource(this.$.powerSource.value);
+  },
+
+  /**
+   * Used to disable Battery/AC idle select dropdowns.
+   * @param {!Array<string>} idleOptions
+   * @return {boolean}
+   * @private
+   */
+  hasSingleOption_(idleOptions) {
+    return idleOptions.length == 1;
   },
 
   /** @private */
-  onIdleSelectChange_() {
+  onAcIdleSelectChange_() {
     const behavior = /** @type {settings.IdleBehavior} */
-        (parseInt(this.$.idleSelect.value, 10));
-    settings.DevicePageBrowserProxyImpl.getInstance().setIdleBehavior(behavior);
+        (parseInt(this.$.acIdleSelect.value, 10));
+    this.browserProxy_.setIdleBehavior(behavior, true /* whenOnAc */);
+    settings.recordSettingChange();
+  },
+
+  /** @private */
+  onBatteryIdleSelectChange_() {
+    const behavior = /** @type {settings.IdleBehavior} */
+        (parseInt(this.$.batteryIdleSelect.value, 10));
+    this.browserProxy_.setIdleBehavior(behavior, false /* whenOnAc */);
     settings.recordSettingChange();
   },
 
@@ -194,7 +222,7 @@
   onLidClosedToggleChange_() {
     // Other behaviors are only displayed when the setting is controlled, in
     // which case the toggle can't be changed by the user.
-    settings.DevicePageBrowserProxyImpl.getInstance().setLidClosedBehavior(
+    this.browserProxy_.setLidClosedBehavior(
         this.$.lidClosedToggle.checked ? settings.LidClosedBehavior.SUSPEND :
                                          settings.LidClosedBehavior.DO_NOTHING);
     settings.recordSettingChange();
@@ -251,22 +279,74 @@
   },
 
   /**
-   * @param {!settings.PowerManagementSettings} browserSettings Current power
-   *     management settings.
+   * @param {!settings.IdleBehavior} idleBehavior
+   * @return {{value: settings.IdleBehavior, name: string}} Idle option
+   *     object that maps to idleBehavior.
    * @private
    */
-  powerManagementSettingsChanged_(browserSettings) {
-    this.idleControlled_ = browserSettings.idleControlled;
-    this.hasLid_ = browserSettings.hasLid;
-    this.updateLidClosedLabelAndPref_(
-        browserSettings.lidClosedBehavior, browserSettings.lidClosedControlled);
+  getIdleOption_(idleBehavior) {
+    switch (idleBehavior) {
+      case settings.IdleBehavior.DISPLAY_OFF_SLEEP:
+        return {
+          value: idleBehavior,
+          name: loadTimeData.getString('powerIdleDisplayOffSleep')
+        };
+      case settings.IdleBehavior.DISPLAY_OFF:
+        return {
+          value: idleBehavior,
+          name: loadTimeData.getString('powerIdleDisplayOff')
+        };
+      case settings.IdleBehavior.DISPLAY_ON:
+        return {
+          value: idleBehavior,
+          name: loadTimeData.getString('powerIdleDisplayOn')
+        };
+      case settings.IdleBehavior.OTHER:
+        return {
+          value: idleBehavior,
+          name: loadTimeData.getString('powerIdleOther')
+        };
+      default:
+        assertNotReached('Unknown IdleBehavior type');
+    }
+  },
 
-    // The idle behavior select element includes an "Other" option when
-    // controlled but omits it otherwise. Make sure that the option is there
-    // before we potentially try to select it.
-    this.async(function() {
-      this.$.idleSelect.value = browserSettings.idleBehavior;
+  /**
+   * @param {!Array<!settings.IdleBehavior>} acIdleBehaviors
+   * @param {!Array<!settings.IdleBehavior>} batteryIdleBehaviors
+   * @private
+   */
+  updateIdleOptions_(acIdleBehaviors, batteryIdleBehaviors) {
+    this.acIdleOptions_ = acIdleBehaviors.map((idleBehavior) => {
+      return this.getIdleOption_(idleBehavior);
     });
+
+    this.batteryIdleOptions_ = batteryIdleBehaviors.map((idleBehavior) => {
+      return this.getIdleOption_(idleBehavior);
+    });
+  },
+
+  /**
+   * @param {!settings.PowerManagementSettings} powerManagementSettings Current
+   *     power management settings.
+   * @private
+   */
+  powerManagementSettingsChanged_(powerManagementSettings) {
+    this.updateIdleOptions_(
+        powerManagementSettings.possibleAcIdleBehaviors || [],
+        powerManagementSettings.possibleBatteryIdleBehaviors || []);
+    this.acIdleManaged_ = powerManagementSettings.acIdleManaged;
+    this.batteryIdleManaged_ = powerManagementSettings.batteryIdleManaged;
+    this.hasLid_ = powerManagementSettings.hasLid;
+    this.updateLidClosedLabelAndPref_(
+        powerManagementSettings.lidClosedBehavior,
+        powerManagementSettings.lidClosedControlled);
+    // Make sure that the option is there before we potentially try to select
+    // it.
+    Polymer.dom.flush();
+    this.currAcIdleBehavior_ = powerManagementSettings.currentAcIdleBehavior;
+    this.currBatteryIdleBehavior_ =
+        powerManagementSettings.currentBatteryIdleBehavior;
   },
 
   /**
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index 514654d..85ce33c 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -966,20 +966,7 @@
   const Origin origin = Origin::Create(url);
 
   if (action == WarningAction::CHANGE_PASSWORD) {
-    // Directly open enterprise change password page in a new tab for
-    // enterprise reuses.
-    if (password_type.account_type() ==
-        ReusedPasswordAccountType::NON_GAIA_ENTERPRISE) {
-      OpenUrl(web_contents, GetEnterpriseChangePasswordURL(),
-              content::Referrer(),
-              /*in_new_tab=*/true);
-      web_contents_with_unhandled_enterprise_reuses_.erase(web_contents);
-      return;
-    }
-
-    // For sync password reuse, open accounts.google.com page in a new tab.
-    OpenUrl(web_contents, GetDefaultChangePasswordURL(), content::Referrer(),
-            /*in_new_tab=*/true);
+    OpenChangePasswordUrl(web_contents, password_type);
     return;
   }
 
diff --git a/chrome/browser/themes/theme_helper.cc b/chrome/browser/themes/theme_helper.cc
index c271144..4a0087e4 100644
--- a/chrome/browser/themes/theme_helper.cc
+++ b/chrome/browser/themes/theme_helper.cc
@@ -300,6 +300,31 @@
                     incognito, theme_supplier);
   };
   switch (id) {
+    case TP::COLOR_OMNIBOX_BACKGROUND: {
+      // TODO(http://crbug.com/878664): Enable for all cases.
+      if (!IsCustomTheme(theme_supplier))
+        break;
+      constexpr float kMinOmniboxToolbarContrast = 1.3f;
+      const SkColor toolbar_color =
+          GetColor(TP::COLOR_TOOLBAR, incognito, theme_supplier);
+      const SkColor endpoint_color =
+          color_utils::GetEndpointColorWithMinContrast(toolbar_color);
+      const SkColor blend_target =
+          (color_utils::GetContrastRatio(toolbar_color, endpoint_color) >=
+           kMinOmniboxToolbarContrast)
+              ? endpoint_color
+              : color_utils::GetColorWithMaxContrast(endpoint_color);
+      return color_utils::BlendForMinContrast(toolbar_color, toolbar_color,
+                                              blend_target,
+                                              kMinOmniboxToolbarContrast)
+          .color;
+    }
+    case TP::COLOR_OMNIBOX_TEXT:
+      // TODO(http://crbug.com/878664): Enable for all cases.
+      if (!IsCustomTheme(theme_supplier))
+        break;
+      return color_utils::GetColorWithMaxContrast(
+          GetColor(TP::COLOR_OMNIBOX_BACKGROUND, incognito, theme_supplier));
     case TP::COLOR_TAB_BACKGROUND_INACTIVE_FRAME_ACTIVE:
       return color_utils::HSLShift(get_frame_color(/*active=*/true),
                                    GetTint(ThemeProperties::TINT_BACKGROUND_TAB,
@@ -591,8 +616,6 @@
     case TP::COLOR_OMNIBOX_TEXT:
     case TP::COLOR_OMNIBOX_RESULTS_TEXT_SELECTED:
       return fg;
-    case TP::COLOR_OMNIBOX_BACKGROUND:
-      return bg;
     case TP::COLOR_OMNIBOX_BACKGROUND_HOVERED:
       return bg_hovered_color();
     case TP::COLOR_OMNIBOX_RESULTS_BG:
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc
index 7431e11f..55cf198 100644
--- a/chrome/browser/themes/theme_properties.cc
+++ b/chrome/browser/themes/theme_properties.cc
@@ -112,6 +112,8 @@
       return SK_ColorWHITE;
     case ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_BACKGROUND:
       return gfx::kGoogleBlue700;
+    // TODO(http://crbug.com/878664): Remove COLOR_OMNIBOX_xxx when these are
+    // consistently autogenerated.
     case ThemeProperties::COLOR_OMNIBOX_TEXT:
       return gfx::kGoogleGrey900;
     case ThemeProperties::COLOR_OMNIBOX_BACKGROUND:
@@ -185,6 +187,8 @@
       return SkColorSetRGB(0x28, 0x28, 0x28);
     case ThemeProperties::COLOR_NTP_LINK:
       return gfx::kGoogleBlue300;
+    // TODO(http://crbug.com/878664): Remove COLOR_OMNIBOX_xxx when these are
+    // consistently autogenerated.
     case ThemeProperties::COLOR_OMNIBOX_TEXT:
       return SK_ColorWHITE;
     case ThemeProperties::COLOR_OMNIBOX_BACKGROUND:
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index f447258..bb81d58 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1999,6 +1999,8 @@
       "webui/settings/chromeos/cups_printers_handler.h",
       "webui/settings/chromeos/date_time_handler.cc",
       "webui/settings/chromeos/date_time_handler.h",
+      "webui/settings/chromeos/device_display_handler.cc",
+      "webui/settings/chromeos/device_display_handler.h",
       "webui/settings/chromeos/device_keyboard_handler.cc",
       "webui/settings/chromeos/device_keyboard_handler.h",
       "webui/settings/chromeos/device_pointer_handler.cc",
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
index a740a3b6..773d5ba 100644
--- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include <algorithm>
 #include <memory>
 #include <utility>
 
@@ -47,6 +48,10 @@
 // The time delta between clicks in which clicks to launch V2 apps are ignored.
 const int kClickSuppressionInMS = 1000;
 
+bool IsAppBrowser(Browser* browser) {
+  return browser->is_type_app() || browser->is_type_app_popup();
+}
+
 // AppMatcher is used to determine if various WebContents instances are
 // associated with a specific app. Clients should call CanMatchWebContents()
 // before iterating through WebContents instances and calling
@@ -74,9 +79,9 @@
   bool CanMatchWebContents() const { return registrar_ || extension_; }
 
   // Returns true if this app matches the given |web_contents|. If
-  // |deprecated_is_app| is true, the application gets first checked against its
-  // original URL since a windowed app might have navigated away from its app
-  // domain.
+  // the browser is an app browser, the application gets first checked against
+  // its original URL since a windowed app might have navigated away from its
+  // app domain.
   // May only be called if CanMatchWebContents() return true.
   bool WebContentMatchesApp(content::WebContents* web_contents,
                             Browser* browser) const {
@@ -93,7 +98,7 @@
 
     // If the browser is an app window, and the app name matches the extension,
     // then the contents match the app.
-    if (browser->deprecated_is_app()) {
+    if (IsAppBrowser(browser)) {
       const Extension* browser_extension =
           ExtensionRegistry::Get(browser->profile())
               ->GetExtensionById(
@@ -138,8 +143,12 @@
 
     // Bookmark apps set to launch in app windows should not match contents
     // running in tabs.
-    if (registrar_->GetAppUserDisplayMode(app_id_) ==
-            web_app::DisplayMode::kStandalone &&
+    if (registrar_->GetAppUserDisplayMode(app_id_) !=
+            web_app::DisplayMode::kBrowser &&
+        // TODO(crbug.com/1054116): when the flag is on, we allow web
+        // contents in a normal browser to match a web app. This is going to
+        // be weird because GetAppMenuItems(0) and HasRunningApplications()
+        // does not consider normal browsers.
         !base::FeatureList::IsEnabled(
             features::kDesktopPWAsWithoutExtensions)) {
       return false;
@@ -187,43 +196,11 @@
       new AppShortcutLauncherItemController(shelf_id));
 }
 
-// static
-std::vector<content::WebContents*>
-AppShortcutLauncherItemController::GetRunningApplications(
-    const std::string& app_id,
-    const GURL& refocus_url) {
-  URLPattern refocus_pattern(URLPattern::SCHEME_ALL);
-  refocus_pattern.SetMatchAllURLs(true);
-
-  if (!refocus_url.is_empty()) {
-    refocus_pattern.SetMatchAllURLs(false);
-    refocus_pattern.Parse(refocus_url.spec());
-  }
-
-  Profile* const profile = ChromeLauncherController::instance()->profile();
-  AppMatcher matcher(profile, app_id, refocus_pattern);
-
-  std::vector<content::WebContents*> items;
-  // It is possible to come here while an app gets loaded.
-  if (!matcher.CanMatchWebContents())
-    return items;
-
-  for (auto* browser : *BrowserList::GetInstance()) {
-    if (!multi_user_util::IsProfileFromActiveUser(browser->profile()))
-      continue;
-    TabStripModel* tab_strip = browser->tab_strip_model();
-    for (int index = 0; index < tab_strip->count(); index++) {
-      content::WebContents* web_contents = tab_strip->GetWebContentsAt(index);
-      if (matcher.WebContentMatchesApp(web_contents, browser))
-        items.push_back(web_contents);
-    }
-  }
-  return items;
-}
-
 AppShortcutLauncherItemController::AppShortcutLauncherItemController(
     const ash::ShelfID& shelf_id)
     : ash::ShelfItemDelegate(shelf_id) {
+  BrowserList::AddObserver(this);
+
   // To detect V1 applications we use their domain and match them against the
   // used URL. This will also work with applications like Google Drive.
   const Extension* extension = GetExtensionForAppID(
@@ -235,7 +212,9 @@
   }
 }
 
-AppShortcutLauncherItemController::~AppShortcutLauncherItemController() {}
+AppShortcutLauncherItemController::~AppShortcutLauncherItemController() {
+  BrowserList::RemoveObserver(this);
+}
 
 void AppShortcutLauncherItemController::ItemSelected(
     std::unique_ptr<ui::Event> event,
@@ -244,22 +223,23 @@
     ItemSelectedCallback callback) {
   // In case of a keyboard event, we were called by a hotkey. In that case we
   // activate the next item in line if an item of our list is already active.
-  if (event && event->type() == ui::ET_KEY_RELEASED && AdvanceToNextApp()) {
-    std::move(callback).Run(ash::SHELF_ACTION_WINDOW_ACTIVATED, {});
-    return;
+  if (event && event->type() == ui::ET_KEY_RELEASED) {
+    auto optional_action = AdvanceToNextApp();
+    if (optional_action.has_value()) {
+      std::move(callback).Run(optional_action.value(), {});
+      return;
+    }
   }
 
-  content::WebContents* content = GetLRUApplication();
-  if (!content) {
+  AppMenuItems items = GetAppMenuItems(event ? event->flags() : ui::EF_NONE);
+  if (items.empty()) {
     // Ideally we come here only once. After that ShellLauncherItemController
     // will take over when the shell window gets opened. However there are apps
     // which take a lot of time for pre-processing (like the files app) before
     // they open a window. Since there is currently no other way to detect if an
     // app was started we suppress any further clicks within a special time out.
     if (IsV2App() && !AllowNextLaunchAttempt()) {
-      std::move(callback).Run(
-          ash::SHELF_ACTION_NONE,
-          GetAppMenuItems(event ? event->flags() : ui::EF_NONE));
+      std::move(callback).Run(ash::SHELF_ACTION_NONE, std::move(items));
       return;
     }
 
@@ -271,26 +251,53 @@
     return;
   }
 
-  if (GetRunningApplications().size() == 1) {
-    std::move(callback).Run(ActivateContent(content), {});
+  if (items.size() == 1) {
+    DCHECK(AppMenuSize() == 1);
+    std::move(callback).Run(
+        app_menu_cached_by_browsers_
+            ? ChromeLauncherController::instance()
+                  ->ActivateWindowOrMinimizeIfActive(
+                      // We don't need to check nullptr here because
+                      // we just called GetAppMenuItems() above to update it.
+                      app_menu_browsers_[0]->window(), true)
+            : ActivateContentOrMinimize(app_menu_web_contents_[0], true),
+        {});
   } else {
     // Multiple items, a menu will be shown. No need to activate the most
     // recently active item.
-    std::move(callback).Run(
-        ash::SHELF_ACTION_NONE,
-        GetAppMenuItems(event ? event->flags() : ui::EF_NONE));
+    std::move(callback).Run(ash::SHELF_ACTION_NONE, std::move(items));
   }
 }
 
+bool AppShortcutLauncherItemController::HasRunningApplications() {
+  return IsWindowedWebApp() ? !GetAppBrowsers().empty()
+                            : !GetAppWebContents().empty();
+}
+
 ash::ShelfItemDelegate::AppMenuItems
 AppShortcutLauncherItemController::GetAppMenuItems(int event_flags) {
-  app_menu_items_ = GetRunningApplications();
   ChromeLauncherController* controller = ChromeLauncherController::instance();
   AppMenuItems items;
-  for (content::WebContents* item : app_menu_items_) {
-    items.push_back({controller->GetAppMenuTitle(item),
-                     controller->GetAppMenuIcon(item).AsImageSkia()});
+  auto add_menu_item = [&controller,
+                        &items](content::WebContents* web_contents) {
+    items.push_back({controller->GetAppMenuTitle(web_contents),
+                     controller->GetAppMenuIcon(web_contents).AsImageSkia()});
+  };
+
+  if (IsWindowedWebApp() && !(event_flags & ui::EF_SHIFT_DOWN)) {
+    app_menu_browsers_ = GetAppBrowsers();
+    app_menu_cached_by_browsers_ = true;
+    for (auto* browser : app_menu_browsers_) {
+      add_menu_item(browser->tab_strip_model()->GetActiveWebContents());
+    }
+  } else {
+    app_menu_web_contents_ = GetAppWebContents();
+    app_menu_cached_by_browsers_ = false;
+    for (auto* web_contents : app_menu_web_contents_) {
+      add_menu_item(web_contents);
+    }
   }
+
   return items;
 }
 
@@ -310,56 +317,82 @@
   if (from_context_menu && ExecuteContextMenuCommand(command_id, event_flags))
     return;
 
-  if (static_cast<size_t>(command_id) >= app_menu_items_.size()) {
-    app_menu_items_.clear();
+  if (static_cast<size_t>(command_id) >= AppMenuSize()) {
+    ClearAppMenu();
     return;
   }
 
-  // If the web contents was destroyed while the menu was open, then the invalid
-  // pointer cached in |app_menu_items_| should yield a null browser or kNoTab.
-  content::WebContents* web_contents = app_menu_items_[command_id];
-  Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
-  TabStripModel* tab_strip = browser ? browser->tab_strip_model() : nullptr;
-  const int index = tab_strip ? tab_strip->GetIndexOfWebContents(web_contents)
-                              : TabStripModel::kNoTab;
-  if (index != TabStripModel::kNoTab) {
-    if (event_flags & (ui::EF_SHIFT_DOWN | ui::EF_MIDDLE_MOUSE_BUTTON)) {
-      tab_strip->CloseWebContentsAt(index, TabStripModel::CLOSE_USER_GESTURE);
-    } else {
-      multi_user_util::MoveWindowToCurrentDesktop(
-          browser->window()->GetNativeWindow());
-      tab_strip->ActivateTabAt(index);
-      browser->window()->Show();
-      browser->window()->Activate();
+  bool should_close =
+      event_flags & (ui::EF_SHIFT_DOWN | ui::EF_MIDDLE_MOUSE_BUTTON);
+  auto activate_browser = [](Browser* browser) {
+    multi_user_util::MoveWindowToCurrentDesktop(
+        browser->window()->GetNativeWindow());
+    browser->window()->Show();
+    browser->window()->Activate();
+  };
+
+  if (app_menu_cached_by_browsers_) {
+    Browser* browser = app_menu_browsers_[command_id];
+    if (browser) {
+      if (should_close)
+        browser->tab_strip_model()->CloseAllTabs();
+      else
+        activate_browser(browser);
+    }
+  } else {
+    // If the web contents was destroyed while the menu was open, then the
+    // invalid pointer cached in |app_menu_web_contents_| should yield a null
+    // browser or kNoTab.
+    content::WebContents* web_contents = app_menu_web_contents_[command_id];
+    Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
+    TabStripModel* tab_strip = browser ? browser->tab_strip_model() : nullptr;
+    const int index = tab_strip ? tab_strip->GetIndexOfWebContents(web_contents)
+                                : TabStripModel::kNoTab;
+    if (index != TabStripModel::kNoTab) {
+      if (should_close) {
+        tab_strip->CloseWebContentsAt(index, TabStripModel::CLOSE_USER_GESTURE);
+      } else {
+        tab_strip->ActivateTabAt(index);
+        activate_browser(browser);
+      }
     }
   }
 
-  app_menu_items_.clear();
+  ClearAppMenu();
 }
 
 void AppShortcutLauncherItemController::Close() {
   // Close all running 'programs' of this type.
-  std::vector<content::WebContents*> content =
-      ChromeLauncherController::instance()->GetV1ApplicationsFromAppId(
-          app_id());
-  for (size_t i = 0; i < content.size(); i++) {
-    Browser* browser = chrome::FindBrowserWithWebContents(content[i]);
-    if (!browser ||
-        !multi_user_util::IsProfileFromActiveUser(browser->profile()))
-      continue;
-    TabStripModel* tab_strip = browser->tab_strip_model();
-    int index = tab_strip->GetIndexOfWebContents(content[i]);
-    DCHECK(index != TabStripModel::kNoTab);
-    tab_strip->CloseWebContentsAt(index, TabStripModel::CLOSE_NONE);
+  if (IsWindowedWebApp()) {
+    for (Browser* browser : GetAppBrowsers())
+      browser->tab_strip_model()->CloseAllTabs();
+  } else {
+    for (content::WebContents* item : GetAppWebContents()) {
+      Browser* browser = chrome::FindBrowserWithWebContents(item);
+      if (!browser ||
+          !multi_user_util::IsProfileFromActiveUser(browser->profile())) {
+        continue;
+      }
+      TabStripModel* tab_strip = browser->tab_strip_model();
+      int index = tab_strip->GetIndexOfWebContents(item);
+      DCHECK(index != TabStripModel::kNoTab);
+      tab_strip->CloseWebContentsAt(index, TabStripModel::CLOSE_NONE);
+    }
   }
 }
 
-std::vector<content::WebContents*>
-AppShortcutLauncherItemController::GetRunningApplications() {
-  return GetRunningApplications(app_id(), refocus_url_);
+void AppShortcutLauncherItemController::OnBrowserClosing(Browser* browser) {
+  if (!app_menu_cached_by_browsers_)
+    return;
+  // Reset pointers to the closed browser, but leave menu indices intact.
+  auto it =
+      std::find(app_menu_browsers_.begin(), app_menu_browsers_.end(), browser);
+  if (it != app_menu_browsers_.end())
+    *it = nullptr;
 }
 
-content::WebContents* AppShortcutLauncherItemController::GetLRUApplication() {
+std::vector<content::WebContents*>
+AppShortcutLauncherItemController::GetAppWebContents() {
   URLPattern refocus_pattern(URLPattern::SCHEME_ALL);
   refocus_pattern.SetMatchAllURLs(true);
 
@@ -371,47 +404,44 @@
   Profile* const profile = ChromeLauncherController::instance()->profile();
   AppMatcher matcher(profile, app_id(), refocus_pattern);
 
+  std::vector<content::WebContents*> items;
   // It is possible to come here while an app gets loaded.
   if (!matcher.CanMatchWebContents())
-    return nullptr;
+    return items;
 
-  const BrowserList* browser_list = BrowserList::GetInstance();
-  for (BrowserList::const_reverse_iterator it =
-           browser_list->begin_last_active();
-       it != browser_list->end_last_active(); ++it) {
-    Browser* browser = *it;
-    if (!multi_user_util::IsProfileFromActiveUser(browser->profile()))
-      continue;
-    TabStripModel* tab_strip = browser->tab_strip_model();
-    // We start to enumerate from the active index.
-    int active_index = tab_strip->active_index();
-    for (int index = 0; index < tab_strip->count(); index++) {
-      content::WebContents* web_contents = tab_strip->GetWebContentsAt(
-          (index + active_index) % tab_strip->count());
-      if (matcher.WebContentMatchesApp(web_contents, browser))
-        return web_contents;
-    }
-  }
-  // Coming here our application was not in the LRU list. This could have
-  // happened because it did never get activated yet. So check the browser list
-  // as well.
-  for (BrowserList::const_iterator it = browser_list->begin();
-       it != browser_list->end(); ++it) {
-    Browser* browser = *it;
+  for (auto* browser : *BrowserList::GetInstance()) {
     if (!multi_user_util::IsProfileFromActiveUser(browser->profile()))
       continue;
     TabStripModel* tab_strip = browser->tab_strip_model();
     for (int index = 0; index < tab_strip->count(); index++) {
       content::WebContents* web_contents = tab_strip->GetWebContentsAt(index);
       if (matcher.WebContentMatchesApp(web_contents, browser))
-        return web_contents;
+        items.push_back(web_contents);
     }
   }
-  return nullptr;
+  return items;
 }
 
-ash::ShelfAction AppShortcutLauncherItemController::ActivateContent(
-    content::WebContents* content) {
+std::vector<Browser*> AppShortcutLauncherItemController::GetAppBrowsers() {
+  DCHECK(IsWindowedWebApp());
+  std::vector<Browser*> browsers;
+  for (Browser* browser : *BrowserList::GetInstance()) {
+    if (!multi_user_util::IsProfileFromActiveUser(browser->profile()))
+      continue;
+    if (!IsAppBrowser(browser))
+      continue;
+
+    if (web_app::GetAppIdFromApplicationName(browser->app_name()) == app_id() &&
+        browser->tab_strip_model()->GetActiveWebContents()) {
+      browsers.push_back(browser);
+    }
+  }
+  return browsers;
+}
+
+ash::ShelfAction AppShortcutLauncherItemController::ActivateContentOrMinimize(
+    content::WebContents* content,
+    bool allow_minimize) {
   Browser* browser = chrome::FindBrowserWithWebContents(content);
   TabStripModel* tab_strip = browser->tab_strip_model();
   int index = tab_strip->GetIndexOfWebContents(content);
@@ -421,36 +451,46 @@
   if (index != old_index)
     tab_strip->ActivateTabAt(index);
   return ChromeLauncherController::instance()->ActivateWindowOrMinimizeIfActive(
-      browser->window(),
-      index == old_index && GetRunningApplications().size() == 1);
+      browser->window(), index == old_index && allow_minimize);
 }
 
-bool AppShortcutLauncherItemController::AdvanceToNextApp() {
-  std::vector<content::WebContents*> items = GetRunningApplications();
-  if (items.size() >= 1) {
-    Browser* browser = chrome::FindLastActive();
-    // The last active browser is not necessarily the active window. The window
-    // could be a v2 app or ARC app.
-    if (browser && browser->window()->IsActive()) {
+base::Optional<ash::ShelfAction>
+AppShortcutLauncherItemController::AdvanceToNextApp() {
+  Browser* browser = chrome::FindLastActive();
+  // The last active browser is not necessarily the active window. The window
+  // could be a v2 app or ARC app.
+  if (browser && browser->window()->IsActive()) {
+    if (IsWindowedWebApp()) {
+      std::vector<Browser*> browsers = GetAppBrowsers();
+      auto it = std::find(browsers.cbegin(), browsers.cend(), browser);
+      if (it == browsers.cend()) {
+        return base::nullopt;
+      }
+      if (browsers.size() == 1) {
+        ash_util::BounceWindow(browser->window()->GetNativeWindow());
+        return ash::SHELF_ACTION_NONE;
+      }
+      size_t index = (it - browsers.cbegin() + 1) % browsers.size();
+      browsers[index]->window()->Show();
+      browsers[index]->window()->Activate();
+      return ash::SHELF_ACTION_WINDOW_ACTIVATED;
+    } else {
+      std::vector<content::WebContents*> items = GetAppWebContents();
       TabStripModel* tab_strip = browser->tab_strip_model();
-      content::WebContents* active =
-          tab_strip->GetWebContentsAt(tab_strip->active_index());
-      std::vector<content::WebContents*>::const_iterator i(
-          std::find(items.begin(), items.end(), active));
-      if (i != items.end()) {
+      content::WebContents* active_content = tab_strip->GetActiveWebContents();
+      auto it = std::find(items.cbegin(), items.cend(), active_content);
+      if (it != items.cend()) {
         if (items.size() == 1) {
-          // If there is only a single item available, we animate it upon key
-          // action.
           ash_util::BounceWindow(browser->window()->GetNativeWindow());
-        } else {
-          int index = (static_cast<int>(i - items.begin()) + 1) % items.size();
-          ActivateContent(items[index]);
+          return ash::SHELF_ACTION_NONE;
         }
-        return true;
+        size_t index = (it - items.cbegin() + 1) % items.size();
+        ActivateContentOrMinimize(items[index], false);
+        return ash::SHELF_ACTION_WINDOW_ACTIVATED;
       }
     }
   }
-  return false;
+  return base::nullopt;
 }
 
 bool AppShortcutLauncherItemController::IsV2App() {
@@ -469,3 +509,26 @@
   }
   return false;
 }
+
+bool AppShortcutLauncherItemController::IsWindowedWebApp() {
+  if (web_app::WebAppProviderBase* provider =
+          web_app::WebAppProviderBase::GetProviderBase(
+              ChromeLauncherController::instance()->profile())) {
+    web_app::AppRegistrar& registrar = provider->registrar();
+    if (registrar.IsLocallyInstalled(app_id())) {
+      return registrar.GetAppUserDisplayMode(app_id()) !=
+             web_app::DisplayMode::kBrowser;
+    }
+  }
+  return false;
+}
+
+size_t AppShortcutLauncherItemController::AppMenuSize() {
+  return app_menu_cached_by_browsers_ ? app_menu_browsers_.size()
+                                      : app_menu_web_contents_.size();
+}
+
+void AppShortcutLauncherItemController::ClearAppMenu() {
+  app_menu_browsers_.clear();
+  app_menu_web_contents_.clear();
+}
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
index aad943c..02e723b 100644
--- a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h
@@ -10,14 +10,18 @@
 #include <vector>
 
 #include "ash/public/cpp/shelf_item_delegate.h"
+#include "ash/public/cpp/shelf_types.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "base/time/time.h"
+#include "chrome/browser/ui/browser_list_observer.h"
 #include "url/gurl.h"
 
 namespace content {
 class WebContents;
 }
 
+class Browser;
 class ShelfContextMenu;
 
 // Item controller for an app shortcut.
@@ -28,17 +32,14 @@
 //
 // Non-platform app types do not use AppWindows. This delegate is not replaced
 // when browser windows are opened for those app types.
-class AppShortcutLauncherItemController : public ash::ShelfItemDelegate {
+class AppShortcutLauncherItemController : public ash::ShelfItemDelegate,
+                                          public BrowserListObserver {
  public:
   ~AppShortcutLauncherItemController() override;
 
   static std::unique_ptr<AppShortcutLauncherItemController> Create(
       const ash::ShelfID& shelf_id);
 
-  static std::vector<content::WebContents*> GetRunningApplications(
-      const std::string& app_id,
-      const GURL& refocus_url = GURL());
-
   // ash::ShelfItemDelegate overrides:
   void ItemSelected(std::unique_ptr<ui::Event> event,
                     int64_t display_id,
@@ -53,28 +54,34 @@
                       int64_t display_id) override;
   void Close() override;
 
-  std::vector<content::WebContents*> GetRunningApplications();
-
   // Get the refocus url pattern, which can be used to identify this application
   // from a URL link.
   const GURL& refocus_url() const { return refocus_url_; }
   // Set the refocus url pattern. Used by unit tests.
   void set_refocus_url(const GURL& refocus_url) { refocus_url_ = refocus_url; }
 
+  bool HasRunningApplications();
+
  protected:
   explicit AppShortcutLauncherItemController(const ash::ShelfID& shelf_id);
 
  private:
-  // Get the last running application.
-  content::WebContents* GetLRUApplication();
+  // BrowserListObserver:
+  void OnBrowserClosing(Browser* browser) override;
 
-  // Activate the browser with the given |content| and show the associated tab.
-  // Returns the action performed by activating the content.
-  ash::ShelfAction ActivateContent(content::WebContents* content);
+  std::vector<content::WebContents*> GetAppWebContents();
+  std::vector<Browser*> GetAppBrowsers();
 
-  // Advance to the next item if an owned item is already active. The function
-  // will return true if it has successfully advanced.
-  bool AdvanceToNextApp();
+  // Activate the browser with the given |content| and show the associated tab,
+  // or minimize the browser if it is already active. Returns the action
+  // performed by activating the content.
+  ash::ShelfAction ActivateContentOrMinimize(content::WebContents* content,
+                                             bool allow_minimize);
+
+  // If an owned item is already active, this function advances to the next item
+  // (or bounce the browser if there is only one item) and returns a shelf
+  // action. Otherwise, it returns nullopt.
+  base::Optional<ash::ShelfAction> AdvanceToNextApp();
 
   // Returns true if the application is a V2 app.
   bool IsV2App();
@@ -82,14 +89,23 @@
   // Returns true if it is allowed to try starting a V2 app again.
   bool AllowNextLaunchAttempt();
 
+  bool IsWindowedWebApp();
+
+  size_t AppMenuSize();
+  void ClearAppMenu();
+
   GURL refocus_url_;
 
   // Since V2 applications can be undetectable after launching, this timer is
   // keeping track of the last launch attempt.
   base::Time last_launch_attempt_;
 
-  // The cached list of open app web contents shown in an application menu.
-  std::vector<content::WebContents*> app_menu_items_;
+  // The cached lists of open app shown in an application menu. We either cache
+  // by the web contents or by the browsers, and this is indicated by the value
+  // of |app_menu_cached_by_browsers_|.
+  std::vector<content::WebContents*> app_menu_web_contents_;
+  std::vector<Browser*> app_menu_browsers_;
+  bool app_menu_cached_by_browsers_ = false;
 
   std::unique_ptr<ShelfContextMenu> context_menu_;
 
diff --git a/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller_browsertest.cc
new file mode 100644
index 0000000..f7356e7
--- /dev/null
+++ b/chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller_browsertest.cc
@@ -0,0 +1,156 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h"
+
+#include "ash/public/cpp/shelf_model.h"
+#include "ash/public/cpp/shelf_types.h"
+#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.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_app_manager.h"
+#include "chrome/browser/web_applications/web_app_provider.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "ui/events/event_constants.h"
+
+// Unit tests for the left click menu and interaction with the menu items. There
+// are integration tests in ./chrome_launcher_controller_browsertest.cc which
+// covers different cases in AppShortcutLauncherItemController::ItemSelected().
+//
+// We do tests on the terminal system web app because it uses tabbed window,
+// which allows us to test app menu with either windows or tabs (shift click).
+class AppShortcutLauncherItemControllerBrowserTest
+    : public InProcessBrowserTest {
+ protected:
+  void SetUpOnMainThread() override {
+    controller_ = ChromeLauncherController::instance();
+    ASSERT_TRUE(controller_);
+  }
+
+  void InstallApp() {
+    web_app::WebAppProvider::Get(browser()->profile())
+        ->system_web_app_manager()
+        .InstallSystemAppsForTesting();
+
+    app_id_ = *web_app::GetAppIdForSystemWebApp(
+        browser()->profile(), web_app::SystemAppType::TERMINAL);
+    app_shelf_id_ = ash::ShelfID(app_id_);
+    controller_->PinAppWithID(app_id_);
+  }
+
+  Browser* LaunchApp() {
+    Browser* app_browser = web_app::LaunchSystemWebApp(
+        browser()->profile(), web_app::SystemAppType::TERMINAL,
+        GURL("chrome-untrusted://terminal/html/terminal.html"));
+    DCHECK(app_browser);
+    return app_browser;
+  }
+
+  ash::ShelfItemDelegate* GetShelfItemDelegate() {
+    return controller_->shelf_model()->GetShelfItemDelegate(app_shelf_id_);
+  }
+
+  ChromeLauncherController* controller_;
+
+  web_app::AppId app_id_;
+  ash::ShelfID app_shelf_id_;
+};
+
+// Test interacting with the app menu without shift key down: the app menu has
+// one entry per browser window.
+IN_PROC_BROWSER_TEST_F(AppShortcutLauncherItemControllerBrowserTest,
+                       AppMenuByWindows) {
+  InstallApp();
+
+  EXPECT_EQ(0u, GetShelfItemDelegate()->GetAppMenuItems(0).size());
+
+  // Launch an app window.
+  Browser* app_browser0 = LaunchApp();
+  EXPECT_EQ(1u, GetShelfItemDelegate()->GetAppMenuItems(0).size());
+
+  // Launch two new app windows.
+  Browser* app_browser1 = LaunchApp();
+  LaunchApp();
+  EXPECT_EQ(3u, GetShelfItemDelegate()->GetAppMenuItems(0).size());
+
+  // Open a new tab in an existing app browser. There are still 3 window items.
+  AddBlankTabAndShow(app_browser1);
+  EXPECT_EQ(3u, GetShelfItemDelegate()->GetAppMenuItems(0).size());
+
+  // Clicking the first item in the menu should activate the first app window.
+  EXPECT_FALSE(app_browser0->window()->IsActive());
+  GetShelfItemDelegate()->GetAppMenuItems(0);
+  GetShelfItemDelegate()->ExecuteCommand(/*from_context_menu=*/false,
+                                         /*command_id=*/0, ui::EF_NONE,
+                                         display::kInvalidDisplayId);
+  EXPECT_TRUE(app_browser0->window()->IsActive());
+
+  // Clicking on a closed item should not crash.
+  GetShelfItemDelegate()->GetAppMenuItems(0);
+  CloseBrowserSynchronously(app_browser0);
+  GetShelfItemDelegate()->ExecuteCommand(/*from_context_menu=*/false,
+                                         /*command_id=*/0, ui::EF_NONE,
+                                         display::kInvalidDisplayId);
+
+  // Shift-clicking on an item should close it.
+  EXPECT_EQ(2u, GetShelfItemDelegate()->GetAppMenuItems(0).size());
+  GetShelfItemDelegate()->ExecuteCommand(/*from_context_menu=*/false,
+                                         /*command_id=*/0, ui::EF_SHIFT_DOWN,
+                                         display::kInvalidDisplayId);
+  EXPECT_EQ(1u, GetShelfItemDelegate()->GetAppMenuItems(0).size());
+}
+
+// Test interacting with the app menu with shift key down: the app menu has
+// one entry per tabs.
+IN_PROC_BROWSER_TEST_F(AppShortcutLauncherItemControllerBrowserTest,
+                       AppMenuByTabs) {
+  InstallApp();
+
+  EXPECT_EQ(0u,
+            GetShelfItemDelegate()->GetAppMenuItems(ui::EF_SHIFT_DOWN).size());
+
+  // Launch an app window.
+  Browser* app_browser0 = LaunchApp();
+  EXPECT_EQ(1u,
+            GetShelfItemDelegate()->GetAppMenuItems(ui::EF_SHIFT_DOWN).size());
+
+  // Launch a new app window.
+  Browser* app_browser1 = LaunchApp();
+  EXPECT_EQ(2u,
+            GetShelfItemDelegate()->GetAppMenuItems(ui::EF_SHIFT_DOWN).size());
+
+  // Open a new tab in an existing app browser. There are 3 tab items.
+  AddBlankTabAndShow(app_browser1);
+  EXPECT_EQ(3u,
+            GetShelfItemDelegate()->GetAppMenuItems(ui::EF_SHIFT_DOWN).size());
+
+  // Clicking the second item in the menu should activate the first tab in the
+  // second window.
+  app_browser1->tab_strip_model()->ActivateTabAt(1);
+  app_browser1->window()->Minimize();
+  GetShelfItemDelegate()->GetAppMenuItems(ui::EF_SHIFT_DOWN);
+  GetShelfItemDelegate()->ExecuteCommand(/*from_context_menu=*/false,
+                                         /*command_id=*/1, ui::EF_NONE,
+                                         display::kInvalidDisplayId);
+  EXPECT_TRUE(app_browser1->window()->IsActive());
+  EXPECT_TRUE(app_browser1->tab_strip_model()->active_index() == 0);
+
+  // Clicking on a closed item should not crash.
+  GetShelfItemDelegate()->GetAppMenuItems(ui::EF_SHIFT_DOWN);
+  CloseBrowserSynchronously(app_browser0);
+  GetShelfItemDelegate()->ExecuteCommand(/*from_context_menu=*/false,
+                                         /*command_id=*/0, ui::EF_NONE,
+                                         display::kInvalidDisplayId);
+
+  // Shift-clicking on a item should close it.
+  EXPECT_EQ(2u,
+            GetShelfItemDelegate()->GetAppMenuItems(ui::EF_SHIFT_DOWN).size());
+  GetShelfItemDelegate()->ExecuteCommand(/*from_context_menu=*/false,
+                                         /*command_id=*/0, ui::EF_SHIFT_DOWN,
+                                         display::kInvalidDisplayId);
+  EXPECT_EQ(1u,
+            GetShelfItemDelegate()->GetAppMenuItems(ui::EF_SHIFT_DOWN).size());
+}
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
index 85bed54..8769f654 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -512,7 +512,7 @@
 
   std::unique_ptr<AppShortcutLauncherItemController> item_delegate =
       AppShortcutLauncherItemController::Create(shelf_id);
-  if (!item_delegate->GetRunningApplications().empty()) {
+  if (item_delegate->HasRunningApplications()) {
     SelectItemWithSource(item_delegate.get(), source, display_id);
   } else {
     LaunchApp(shelf_id, source, event_flags, display_id);
@@ -693,20 +693,6 @@
                   : ash::ShelfItemDelegate::AppMenuItems();
 }
 
-std::vector<content::WebContents*>
-ChromeLauncherController::GetV1ApplicationsFromAppId(
-    const std::string& app_id) {
-  // Use the app's shelf item to find that app's windows.
-  const ash::ShelfItem* item = GetItem(ash::ShelfID(app_id));
-  if (!item)
-    return std::vector<content::WebContents*>();
-
-  // This should only be called for apps.
-  DCHECK(item->type == ash::TYPE_APP || item->type == ash::TYPE_PINNED_APP);
-
-  return AppShortcutLauncherItemController::GetRunningApplications(app_id);
-}
-
 std::vector<aura::Window*> ChromeLauncherController::GetArcWindows() {
   if (base::FeatureList::IsEnabled(features::kAppServiceInstanceRegistry)) {
     if (app_service_app_window_controller_)
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
index 4ffe1eac..16cf9c2 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
@@ -194,10 +194,6 @@
   ash::ShelfItemDelegate::AppMenuItems GetAppMenuItemsForTesting(
       const ash::ShelfItem& item);
 
-  // Get the list of all tabs which belong to a certain application type.
-  std::vector<content::WebContents*> GetV1ApplicationsFromAppId(
-      const std::string& app_id);
-
   // Get the list of all ARC app windows.
   std::vector<aura::Window*> GetArcWindows();
 
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index 9ca0241..792c9c3 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -16,6 +16,7 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
+#include "base/system/sys_info.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
@@ -109,6 +110,7 @@
 #if defined(OS_CHROMEOS) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
 const std::string BuildQueryString(Profile* profile) {
+  const std::string board_name = base::SysInfo::GetLsbReleaseBoard();
   std::string region;
   chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic(
       "region", &region);
@@ -131,8 +133,8 @@
   }
 
   const std::string query_string = base::StrCat(
-      {kChromeReleaseNotesURL, "?version=", milestone, "&tags=", region, ",",
-       language, ",", channel_name, ",", user_type});
+      {kChromeReleaseNotesURL, "?version=", milestone, "&tags=", board_name,
+       ",", region, ",", language, ",", channel_name, ",", user_type});
   return query_string;
 }
 
diff --git a/chrome/browser/ui/color/chrome_color_mixers.cc b/chrome/browser/ui/color/chrome_color_mixers.cc
index dd41a85f1..97eb410 100644
--- a/chrome/browser/ui/color/chrome_color_mixers.cc
+++ b/chrome/browser/ui/color/chrome_color_mixers.cc
@@ -4,18 +4,42 @@
 
 #include "chrome/browser/ui/color/chrome_color_mixers.h"
 
+#include "base/bind.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "ui/color/color_id.h"
 #include "ui/color/color_mixer.h"
 #include "ui/color/color_provider.h"
 #include "ui/color/color_recipe.h"
 
+namespace {
+
+constexpr float kMinOmniboxToolbarContrast = 1.3f;
+
+ui::ColorTransform ChooseOmniboxBgBlendTarget() {
+  return base::BindRepeating(
+      [](SkColor input_color, const ui::ColorMixer& mixer) {
+        const SkColor toolbar_color = mixer.GetResultColor(kColorToolbar);
+        const SkColor endpoint_color =
+            color_utils::GetEndpointColorWithMinContrast(toolbar_color);
+        return (color_utils::GetContrastRatio(toolbar_color, endpoint_color) >=
+                kMinOmniboxToolbarContrast)
+                   ? endpoint_color
+                   : color_utils::GetColorWithMaxContrast(endpoint_color);
+      });
+}
+
+}  // namespace
+
 void AddChromeColorMixers(ui::ColorProvider* provider) {
   ui::ColorMixer& mixer = provider->AddMixer();
 
+  // TODO(pkasting): Pre-color pipeline this is only enabled for custom themes.
+  // Agree on consistent behavior before enabling this.
   mixer[kColorOmniboxBackground] = ui::BlendForMinContrast(
-      ui::kColorTextfieldBackground, kColorToolbar, base::nullopt, 1.11f);
-  mixer[kColorOmniboxText] = {ui::kColorTextfieldForeground};
+      kColorToolbar, kColorToolbar, ChooseOmniboxBgBlendTarget(),
+      kMinOmniboxToolbarContrast);
+  mixer[kColorOmniboxText] =
+      ui::GetColorWithMaxContrast(kColorOmniboxBackground);
   // TODO(tluk) Behavior change for dark mode to a darker toolbar color for
   // better color semantics. Follow up with UX team before landing change.
   mixer[kColorToolbar] = {ui::kColorPrimaryBackground};
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
index a9b83963..1773b6a 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -318,7 +318,7 @@
       const AutocompleteMatch& match = GetMatchAtIndex(i);
       if (match.suggestion_group_id.has_value() &&
           match.suggestion_group_id != previous_row_group_id) {
-        row_view->ShowHeader(match.suggestion_group_id,
+        row_view->ShowHeader(match.suggestion_group_id.value(),
                              model_->result().GetHeaderForGroupId(
                                  match.suggestion_group_id.value()));
       } else {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.h b/chrome/browser/ui/views/omnibox/omnibox_result_view.h
index eea4b35..b9cd8598 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.h
@@ -92,8 +92,6 @@
   void SetRichSuggestionImage(const gfx::ImageSkia& image);
 
   // views::ButtonListener:
-
-  // Called when tab switch button pressed, due to being a listener.
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
   // Called to indicate tab switch button has been focused.
diff --git a/chrome/browser/ui/views/omnibox/omnibox_row_view.cc b/chrome/browser/ui/views/omnibox/omnibox_row_view.cc
index 13f6fbdf..1b07e54 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_row_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_row_view.cc
@@ -4,26 +4,78 @@
 
 #include "chrome/browser/ui/views/omnibox/omnibox_row_view.h"
 
+#include "chrome/browser/ui/layout_constants.h"
+#include "chrome/browser/ui/omnibox/omnibox_theme.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_result_view.h"
+#include "components/omnibox/browser/vector_icons.h"
+#include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/button/image_button_factory.h"
+#include "ui/views/controls/highlight_path_generator.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/box_layout.h"
 
-class OmniboxRowView::HeaderView : public views::Label {
+class OmniboxRowView::HeaderView : public views::Label,
+                                   public views::ButtonListener {
  public:
   HeaderView() {
     SetLayoutManager(std::make_unique<views::BoxLayout>(
         views::BoxLayout::Orientation::kHorizontal));
 
     header_text_ = AddChildView(std::make_unique<views::Label>());
+
+    // TODO(tommycli): Add a focus ring.
+    hide_button_ = AddChildView(views::CreateVectorToggleImageButton(this));
+    views::InstallCircleHighlightPathGenerator(hide_button_);
   }
 
-  void SetHeaderText(const base::string16& header_text) {
+  void SetHeader(int suggestion_group_id, const base::string16& header_text) {
+    suggestion_group_id_ = suggestion_group_id;
     header_text_->SetText(header_text);
   }
 
+  // views::View:
+  void OnThemeChanged() override {
+    views::View::OnThemeChanged();
+
+    int dip_size = GetLayoutConstant(LOCATION_BAR_ICON_SIZE);
+    OmniboxPartState part_state =
+        IsMouseHovered() ? OmniboxPartState::HOVERED : OmniboxPartState::NORMAL;
+
+    SkColor color = GetOmniboxColor(GetThemeProvider(),
+                                    OmniboxPart::RESULTS_ICON, part_state);
+    hide_button_->set_ink_drop_base_color(color);
+
+    const gfx::ImageSkia arrow_down =
+        gfx::CreateVectorIcon(omnibox::kChevronIcon, dip_size, color);
+    const gfx::ImageSkia arrow_up =
+        gfx::ImageSkiaOperations::CreateRotatedImage(
+            arrow_down, SkBitmapOperations::ROTATION_180_CW);
+
+    // The "untoggled" button state corresponds with the group being shown.
+    // The "toggled" button state corresponds with the group being hidden.
+    hide_button_->SetImage(views::Button::STATE_NORMAL, arrow_up);
+    hide_button_->SetToggledImage(views::Button::STATE_NORMAL, &arrow_down);
+  }
+
+  // views::ButtonListener:
+  void ButtonPressed(views::Button* sender, const ui::Event& event) override {
+    DCHECK_EQ(sender, hide_button_);
+
+    // TODO(tommycli): Implement toggling the pref here.
+  }
+
  private:
   // The Label containing the header text. This is never nullptr.
   views::Label* header_text_;
+
+  // The button used to toggle hiding suggestions with this header.
+  views::ToggleImageButton* hide_button_;
+
+  // The group ID associated with this header.
+  int suggestion_group_id_ = 0;
 };
 
 OmniboxRowView::OmniboxRowView(std::unique_ptr<OmniboxResultView> result_view) {
@@ -35,13 +87,13 @@
   result_view_ = AddChildView(std::move(result_view));
 }
 
-void OmniboxRowView::ShowHeader(base::Optional<int> suggestion_group_id,
+void OmniboxRowView::ShowHeader(int suggestion_group_id,
                                 const base::string16& header_text) {
   // Create the header (at index 0) if it doesn't exist.
   if (header_view_ == nullptr)
     header_view_ = AddChildViewAt(std::make_unique<HeaderView>(), 0);
 
-  header_view_->SetHeaderText(header_text);
+  header_view_->SetHeader(suggestion_group_id, header_text);
   header_view_->SetVisible(true);
 }
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_row_view.h b/chrome/browser/ui/views/omnibox/omnibox_row_view.h
index c597cdc..27fc6d7a 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_row_view.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_row_view.h
@@ -23,8 +23,7 @@
   explicit OmniboxRowView(std::unique_ptr<OmniboxResultView> result_view);
 
   // Sets the header that appears above this row. Also shows the header.
-  void ShowHeader(base::Optional<int> suggestion_group_id,
-                  const base::string16& header_text);
+  void ShowHeader(int suggestion_group_id, const base::string16& header_text);
 
   // Hides the header.
   void HideHeader();
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc
index baf7171..883958a4 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.cc
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -212,15 +212,6 @@
   params.remove_standard_frame = true;
   params.name = "PictureInPictureWindow";
   params.layer_type = ui::LAYER_NOT_DRAWN;
-#if defined(OS_CHROMEOS)
-  // PIP windows are not activatable by default in ChromeOS. Although this can
-  // be configured in ash/wm/window_state.cc, this is still meaningful when
-  // window service is used, since the activatability isn't shared between
-  // the window server and the client (here). crbug.com/923049 will happen
-  // without this.
-  // TODO(mukai): allow synchronizing activatability and remove this.
-  params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
-#endif
   // Set WidgetDelegate for more control over |widget_|.
   params.delegate = new OverlayWindowWidgetDelegate(overlay_window.get());
 
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
index 8045b2a..12202b8 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -49,6 +49,7 @@
 #include "components/dom_distiller/core/url_constants.h"
 #include "components/dom_distiller/core/url_utils.h"
 #include "components/page_info/page_info.h"
+#include "components/password_manager/core/common/password_manager_features.h"
 #include "components/safe_browsing/buildflags.h"
 #include "components/strings/grit/components_chromium_strings.h"
 #include "components/strings/grit/components_strings.h"
@@ -149,7 +150,10 @@
 
   void AddResetDecisionsLabel();
 
-  void AddPasswordReuseButtons();
+  // Adds the change password and mark site as legitimate buttons.
+  // If |is_saved_password|, adds a check password button instead of
+  // change password button.
+  void AddPasswordReuseButtons(bool is_saved_password);
 
  private:
   // The listener for the buttons in this view.
@@ -299,18 +303,31 @@
   InvalidateLayout();
 }
 
-void BubbleHeaderView::AddPasswordReuseButtons() {
+void BubbleHeaderView::AddPasswordReuseButtons(bool is_saved_password) {
   if (!password_reuse_button_container_->children().empty()) {
     // Ensure all old content is removed from the container before re-adding it.
     password_reuse_button_container_->RemoveAllChildViews(true /* delete */);
   }
 
-  auto change_password_button =
-      views::MdTextButton::CreateSecondaryUiBlueButton(
-          button_listener_,
-          l10n_util::GetStringUTF16(IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON));
-  change_password_button->SetID(
-      PageInfoBubbleView::VIEW_ID_PAGE_INFO_BUTTON_CHANGE_PASSWORD);
+  int change_password_template = 0;
+  if (is_saved_password && !base::FeatureList::IsEnabled(
+                               password_manager::features::kPasswordCheck)) {
+    change_password_template = 0;
+  } else {
+    change_password_template =
+        is_saved_password && base::FeatureList::IsEnabled(
+                                 password_manager::features::kPasswordCheck)
+            ? IDS_PAGE_INFO_CHECK_PASSWORDS_BUTTON
+            : IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON;
+  }
+
+  std::unique_ptr<views::MdTextButton::LabelButton> change_password_button;
+  if (change_password_template) {
+    change_password_button = views::MdTextButton::CreateSecondaryUiBlueButton(
+        button_listener_, l10n_util::GetStringUTF16(change_password_template));
+    change_password_button->SetID(
+        PageInfoBubbleView::VIEW_ID_PAGE_INFO_BUTTON_CHANGE_PASSWORD);
+  }
   auto whitelist_password_reuse_button =
       views::MdTextButton::CreateSecondaryUiButton(
           button_listener_, l10n_util::GetStringUTF16(
@@ -319,11 +336,15 @@
       PageInfoBubbleView::VIEW_ID_PAGE_INFO_BUTTON_WHITELIST_PASSWORD_REUSE);
 
   int kSpacingBetweenButtons = 8;
+  int change_password_button_size =
+      change_password_button
+          ? 0
+          : change_password_button->CalculatePreferredSize().width();
 
   // If these two buttons cannot fit into a single line, stack them vertically.
   bool can_fit_in_one_line =
       (password_reuse_button_container_->width() - kSpacingBetweenButtons) >=
-      (change_password_button->CalculatePreferredSize().width() +
+      (change_password_button_size +
        whitelist_password_reuse_button->CalculatePreferredSize().width());
   auto layout = std::make_unique<views::BoxLayout>(
       can_fit_in_one_line ? views::BoxLayout::Orientation::kHorizontal
@@ -335,15 +356,19 @@
   password_reuse_button_container_->SetLayoutManager(std::move(layout));
 
 #if defined(OS_WIN) || defined(OS_CHROMEOS)
-  password_reuse_button_container_->AddChildView(
-      std::move(change_password_button));
+  if (change_password_button) {
+    password_reuse_button_container_->AddChildView(
+        std::move(change_password_button));
+  }
   password_reuse_button_container_->AddChildView(
       std::move(whitelist_password_reuse_button));
 #else
   password_reuse_button_container_->AddChildView(
       std::move(whitelist_password_reuse_button));
-  password_reuse_button_container_->AddChildView(
-      std::move(change_password_button));
+  if (change_password_button) {
+    password_reuse_button_container_->AddChildView(
+        std::move(change_password_button));
+  }
 #endif
 
   // Add padding at the top.
@@ -825,7 +850,10 @@
   }
 
   if (identity_info.show_change_password_buttons) {
-    header_->AddPasswordReuseButtons();
+    header_->AddPasswordReuseButtons(
+        identity_info.safe_browsing_status ==
+        PageInfo::SafeBrowsingStatus::
+            SAFE_BROWSING_STATUS_SAVED_PASSWORD_REUSE);
   }
   details_text_ = security_description->details;
   header_->SetDetails(security_description->details);
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
index c463423..e02ea55 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
@@ -29,6 +29,7 @@
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/page_info/page_info.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/password_manager/core/common/password_manager_features.h"
 #include "components/safe_browsing/content/password_protection/metrics_util.h"
 #include "components/safe_browsing/core/features.h"
 #include "components/strings/grit/components_strings.h"
@@ -128,7 +129,10 @@
 
 class PageInfoBubbleViewBrowserTest : public DialogBrowserTest {
  public:
-  PageInfoBubbleViewBrowserTest() {}
+  PageInfoBubbleViewBrowserTest() {
+    feature_list_.InitAndEnableFeature(
+        password_manager::features::kPasswordCheck);
+  }
 
   // DialogBrowserTest:
   void ShowUi(const std::string& name) override {
@@ -150,6 +154,7 @@
     constexpr char kSignInSyncPasswordReuse[] = "SignInSyncPasswordReuse";
     constexpr char kSignInNonSyncPasswordReuse[] = "SignInNonSyncPasswordReuse";
     constexpr char kEnterprisePasswordReuse[] = "EnterprisePasswordReuse";
+    constexpr char kSavedPasswordReuse[] = "SavedPasswordReuse";
     constexpr char kMalwareAndBadCert[] = "MalwareAndBadCert";
     constexpr char kMixedContentForm[] = "MixedContentForm";
     constexpr char kMixedContent[] = "MixedContent";
@@ -226,6 +231,9 @@
     } else if (name == kEnterprisePasswordReuse) {
       identity.safe_browsing_status =
           PageInfo::SAFE_BROWSING_STATUS_ENTERPRISE_PASSWORD_REUSE;
+    } else if (name == kSavedPasswordReuse) {
+      identity.safe_browsing_status =
+          PageInfo::SAFE_BROWSING_STATUS_SAVED_PASSWORD_REUSE;
     } else if (name == kMalwareAndBadCert) {
       identity.identity_status = PageInfo::SITE_IDENTITY_STATUS_ERROR;
       identity.certificate = net::ImportCertFromFile(
@@ -382,6 +390,7 @@
 
  private:
   std::vector<PageInfoBubbleView::PageInfoBubbleViewID> expected_identifiers_;
+  base::test::ScopedFeatureList feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(PageInfoBubbleViewBrowserTest);
 };
@@ -543,6 +552,80 @@
             visible_security_state->malicious_content_status);
 }
 
+// Test opening page info bubble that matches
+// SB_THREAT_TYPE_SAVED_PASSWORD_REUSE threat type.
+IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest,
+                       VerifySavedPasswordReusePageInfoBubble) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  base::HistogramTester histograms;
+  ui_test_utils::NavigateToURL(browser(), embedded_test_server()->GetURL("/"));
+
+  // Update security state of the current page to match
+  // SB_THREAT_TYPE_SAVED_PASSWORD_REUSE.
+  safe_browsing::ChromePasswordProtectionService* service =
+      safe_browsing::ChromePasswordProtectionService::
+          GetPasswordProtectionService(browser()->profile());
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  safe_browsing::ReusedPasswordAccountType reused_password_account_type;
+  reused_password_account_type.set_account_type(
+      safe_browsing::ReusedPasswordAccountType::SAVED_PASSWORD);
+  service->set_reused_password_account_type_for_last_shown_warning(
+      reused_password_account_type);
+
+  service->ShowModalWarning(
+      contents, safe_browsing::RequestOutcome::UNKNOWN,
+      safe_browsing::LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED,
+      "unused_token", reused_password_account_type);
+
+  OpenPageInfoBubble(browser());
+  views::View* change_password_button = GetView(
+      browser(), PageInfoBubbleView::VIEW_ID_PAGE_INFO_BUTTON_CHANGE_PASSWORD);
+  views::View* whitelist_password_reuse_button = GetView(
+      browser(),
+      PageInfoBubbleView::VIEW_ID_PAGE_INFO_BUTTON_WHITELIST_PASSWORD_REUSE);
+
+  SecurityStateTabHelper* helper =
+      SecurityStateTabHelper::FromWebContents(contents);
+  std::unique_ptr<security_state::VisibleSecurityState> visible_security_state =
+      helper->GetVisibleSecurityState();
+  ASSERT_EQ(security_state::MALICIOUS_CONTENT_STATUS_SAVED_PASSWORD_REUSE,
+            visible_security_state->malicious_content_status);
+
+  // Verify these two buttons are showing.
+  EXPECT_TRUE(change_password_button->GetVisible());
+  EXPECT_TRUE(whitelist_password_reuse_button->GetVisible());
+
+  // Verify clicking on button will increment corresponding bucket of
+  // PasswordProtection.PageInfoAction.NonGaiaEnterprisePasswordEntry histogram.
+  PerformMouseClickOnView(change_password_button);
+  EXPECT_THAT(
+      histograms.GetAllSamples(safe_browsing::kSavedPasswordPageInfoHistogram),
+      testing::ElementsAre(
+          base::Bucket(static_cast<int>(safe_browsing::WarningAction::SHOWN),
+                       1),
+          base::Bucket(
+              static_cast<int>(safe_browsing::WarningAction::CHANGE_PASSWORD),
+              1)));
+
+  PerformMouseClickOnView(whitelist_password_reuse_button);
+  EXPECT_THAT(
+      histograms.GetAllSamples(safe_browsing::kSavedPasswordPageInfoHistogram),
+      testing::ElementsAre(
+          base::Bucket(static_cast<int>(safe_browsing::WarningAction::SHOWN),
+                       1),
+          base::Bucket(
+              static_cast<int>(safe_browsing::WarningAction::CHANGE_PASSWORD),
+              1),
+          base::Bucket(static_cast<int>(
+                           safe_browsing::WarningAction::MARK_AS_LEGITIMATE),
+                       1)));
+  // Security state will change after whitelisting.
+  visible_security_state = helper->GetVisibleSecurityState();
+  EXPECT_EQ(security_state::MALICIOUS_CONTENT_STATUS_NONE,
+            visible_security_state->malicious_content_status);
+}
+
 // Shows the Page Info bubble for a HTTP page (specifically, about:blank).
 IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, InvokeUi_Insecure) {
   ShowAndVerifyUi();
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc
index 407ca74..e658206 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser_unittest.cc
@@ -70,6 +70,7 @@
                         ash::mojom::DisplayConfigOperation op,
                         ash::mojom::TouchCalibrationPtr calibration,
                         TouchCalibrationCallback callback) override {}
+  void HighlightDisplay(int64_t id) override {}
 
  private:
   mojo::Receiver<ash::mojom::CrosDisplayConfigController> receiver_{this};
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_display_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_display_handler.cc
new file mode 100644
index 0000000..fdfe3d1
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/chromeos/device_display_handler.cc
@@ -0,0 +1,51 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/device_display_handler.h"
+
+#include "ash/public/ash_interfaces.h"
+#include "base/bind.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/values.h"
+#include "content/public/browser/web_ui.h"
+#include "ui/display/types/display_constants.h"
+
+namespace chromeos {
+namespace settings {
+
+DisplayHandler::DisplayHandler() {
+  ash::BindCrosDisplayConfigController(
+      cros_display_config_.BindNewPipeAndPassReceiver());
+}
+
+DisplayHandler::~DisplayHandler() {
+  cros_display_config_->HighlightDisplay(display::kInvalidDisplayId);
+}
+
+void DisplayHandler::RegisterMessages() {
+  web_ui()->RegisterMessageCallback(
+      "highlightDisplay",
+      base::BindRepeating(
+          &DisplayHandler::HandleHighlightDisplay,
+          base::Unretained(this)));  // base::Unretained(this) is acceptable
+                                     // here as |this| is owned by web_ui().
+}
+
+void DisplayHandler::HandleHighlightDisplay(const base::ListValue* args) {
+  AllowJavascript();
+
+  std::string display_id_str;
+  int64_t display_id;
+
+  if (!args->GetString(0, &display_id_str) ||
+      !base::StringToInt64(display_id_str, &display_id)) {
+    cros_display_config_->HighlightDisplay(display::kInvalidDisplayId);
+    return;
+  }
+
+  cros_display_config_->HighlightDisplay(display_id);
+}
+
+}  // namespace settings
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_display_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_display_handler.h
new file mode 100644
index 0000000..62f3f40
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/chromeos/device_display_handler.h
@@ -0,0 +1,42 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_DISPLAY_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_DISPLAY_HANDLER_H_
+
+#include "ash/public/mojom/cros_display_config.mojom.h"
+#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace base {
+class ListValue;
+}  // namespace base
+
+namespace chromeos {
+namespace settings {
+
+// Chrome OS "Displays" settings page UI handler.
+class DisplayHandler : public ::settings::SettingsPageUIHandler {
+ public:
+  DisplayHandler();
+  DisplayHandler(const DisplayHandler&) = delete;
+  DisplayHandler& operator=(const DisplayHandler&) = delete;
+  ~DisplayHandler() override;
+
+  // SettingsPageUIHandler:
+  void RegisterMessages() override;
+  void OnJavascriptAllowed() override {}
+  void OnJavascriptDisallowed() override {}
+
+ private:
+  void HandleHighlightDisplay(const base::ListValue* args);
+
+  mojo::Remote<ash::mojom::CrosDisplayConfigController> cros_display_config_;
+};
+
+}  // namespace settings
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_DISPLAY_HANDLER_H_
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
index 1906a33..a5c66d6 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
@@ -79,11 +79,34 @@
 
 }  // namespace
 
+PowerHandler::IdleBehaviorInfo::IdleBehaviorInfo() = default;
+PowerHandler::IdleBehaviorInfo::~IdleBehaviorInfo() = default;
+
+PowerHandler::IdleBehaviorInfo::IdleBehaviorInfo(
+    const std::set<PowerHandler::IdleBehavior>& possible_behaviors,
+    const PowerHandler::IdleBehavior& current_behavior,
+    const bool is_managed)
+    : possible_behaviors(possible_behaviors),
+      current_behavior(current_behavior),
+      is_managed(is_managed) {}
+
+PowerHandler::IdleBehaviorInfo::IdleBehaviorInfo(const IdleBehaviorInfo& o) =
+    default;
+
 const char PowerHandler::kPowerManagementSettingsChangedName[] =
     "power-management-settings-changed";
-const char PowerHandler::kIdleBehaviorKey[] = "idleBehavior";
-const char PowerHandler::kIdleControlledKey[] = "idleControlled";
+
+const char PowerHandler::kPossibleAcIdleBehaviorsKey[] =
+    "possibleAcIdleBehaviors";
+const char PowerHandler::kPossibleBatteryIdleBehaviorsKey[] =
+    "possibleBatteryIdleBehaviors";
+const char PowerHandler::kCurrentAcIdleBehaviorKey[] = "currentAcIdleBehavior";
+const char PowerHandler::kCurrentBatteryIdleBehaviorKey[] =
+    "currentBatteryIdleBehavior";
 const char PowerHandler::kLidClosedBehaviorKey[] = "lidClosedBehavior";
+const char PowerHandler::kAcIdleManagedKey[] = "acIdleManaged";
+const char PowerHandler::kBatteryIdleManagedKey[] = "batteryIdleManaged";
+
 const char PowerHandler::kLidClosedControlledKey[] = "lidClosedControlled";
 const char PowerHandler::kHasLidKey[] = "hasLid";
 
@@ -96,9 +119,11 @@
   handler_->HandleRequestPowerManagementSettings(&args);
 }
 
-void PowerHandler::TestAPI::SetIdleBehavior(IdleBehavior behavior) {
+void PowerHandler::TestAPI::SetIdleBehavior(IdleBehavior behavior,
+                                            bool when_on_ac) {
   base::ListValue args;
   args.AppendInteger(static_cast<int>(behavior));
+  args.AppendBoolean(when_on_ac);
   handler_->HandleSetIdleBehavior(&args);
 }
 
@@ -205,49 +230,48 @@
   AllowJavascript();
 
   int value = 0;
+  bool when_on_ac = true;
   CHECK(args->GetInteger(0, &value));
+  CHECK(args->GetBoolean(1, &when_on_ac));
+
+  const char* idle_pref = when_on_ac ? ash::prefs::kPowerAcIdleAction
+                                     : ash::prefs::kPowerBatteryIdleAction;
+  const char* screen_dim_delay_pref =
+      when_on_ac ? ash::prefs::kPowerAcScreenDimDelayMs
+                 : ash::prefs::kPowerBatteryScreenDimDelayMs;
+  const char* screen_off_delay_pref =
+      when_on_ac ? ash::prefs::kPowerAcScreenOffDelayMs
+                 : ash::prefs::kPowerBatteryScreenOffDelayMs;
+  const char* screen_lock_delay_pref =
+      when_on_ac ? ash::prefs::kPowerAcScreenLockDelayMs
+                 : ash::prefs::kPowerBatteryScreenLockDelayMs;
+
   switch (static_cast<IdleBehavior>(value)) {
     case IdleBehavior::DISPLAY_OFF_SLEEP:
-      // The default behavior is to turn the display off and sleep. Clear the
-      // prefs so we use the default delays.
-      prefs_->ClearPref(ash::prefs::kPowerAcIdleAction);
-      prefs_->ClearPref(ash::prefs::kPowerAcScreenDimDelayMs);
-      prefs_->ClearPref(ash::prefs::kPowerAcScreenOffDelayMs);
-      prefs_->ClearPref(ash::prefs::kPowerAcScreenLockDelayMs);
-      prefs_->ClearPref(ash::prefs::kPowerBatteryIdleAction);
-      prefs_->ClearPref(ash::prefs::kPowerBatteryScreenDimDelayMs);
-      prefs_->ClearPref(ash::prefs::kPowerBatteryScreenOffDelayMs);
-      prefs_->ClearPref(ash::prefs::kPowerBatteryScreenLockDelayMs);
+      // The default behavior is to turn the display off and sleep.
+      // Clear the prefs so we use the default delays.
+      prefs_->ClearPref(idle_pref);
+      prefs_->ClearPref(screen_dim_delay_pref);
+      prefs_->ClearPref(screen_off_delay_pref);
+      prefs_->ClearPref(screen_lock_delay_pref);
       break;
     case IdleBehavior::DISPLAY_OFF:
-      // Override idle actions to keep the system awake, but use the default
-      // screen delays.
-      prefs_->SetInteger(ash::prefs::kPowerAcIdleAction,
-                         PowerPolicyController::ACTION_DO_NOTHING);
-      prefs_->ClearPref(ash::prefs::kPowerAcScreenDimDelayMs);
-      prefs_->ClearPref(ash::prefs::kPowerAcScreenOffDelayMs);
-      prefs_->ClearPref(ash::prefs::kPowerAcScreenLockDelayMs);
-      prefs_->SetInteger(ash::prefs::kPowerBatteryIdleAction,
-                         PowerPolicyController::ACTION_DO_NOTHING);
-      prefs_->ClearPref(ash::prefs::kPowerBatteryScreenDimDelayMs);
-      prefs_->ClearPref(ash::prefs::kPowerBatteryScreenOffDelayMs);
-      prefs_->ClearPref(ash::prefs::kPowerBatteryScreenLockDelayMs);
+      // Override idle actions to keep the system awake, but use the
+      // default screen delays.
+      prefs_->SetInteger(idle_pref, PowerPolicyController::ACTION_DO_NOTHING);
+      prefs_->ClearPref(screen_dim_delay_pref);
+      prefs_->ClearPref(screen_off_delay_pref);
+      prefs_->ClearPref(screen_lock_delay_pref);
       break;
     case IdleBehavior::DISPLAY_ON:
-      // Override idle actions and set screen delays to 0 in order to disable
-      // them (i.e. keep the screen on).
-      prefs_->SetInteger(ash::prefs::kPowerAcIdleAction,
-                         PowerPolicyController::ACTION_DO_NOTHING);
-      prefs_->SetInteger(ash::prefs::kPowerAcScreenDimDelayMs, 0);
-      prefs_->SetInteger(ash::prefs::kPowerAcScreenOffDelayMs, 0);
-      prefs_->SetInteger(ash::prefs::kPowerAcScreenLockDelayMs, 0);
-      prefs_->SetInteger(ash::prefs::kPowerBatteryIdleAction,
-                         PowerPolicyController::ACTION_DO_NOTHING);
-      prefs_->SetInteger(ash::prefs::kPowerBatteryScreenDimDelayMs, 0);
-      prefs_->SetInteger(ash::prefs::kPowerBatteryScreenOffDelayMs, 0);
-      prefs_->SetInteger(ash::prefs::kPowerBatteryScreenLockDelayMs, 0);
+      // Override idle actions and set screen delays to 0 in order to
+      // disable them (i.e. keep the screen on).
+      prefs_->SetInteger(idle_pref, PowerPolicyController::ACTION_DO_NOTHING);
+      prefs_->SetInteger(screen_dim_delay_pref, 0);
+      prefs_->SetInteger(screen_off_delay_pref, 0);
+      prefs_->SetInteger(screen_lock_delay_pref, 0);
       break;
-    default:
+    case IdleBehavior::OTHER:
       NOTREACHED() << "Invalid idle behavior " << value;
   }
 }
@@ -336,32 +360,10 @@
 }
 
 void PowerHandler::SendPowerManagementSettings(bool force) {
-  // Infer the idle behavior based on the idle action (determining whether we'll
-  // sleep eventually or not) and the AC screen-off delay. Policy can request
-  // more-nuanced combinations of AC/battery actions and delays, but we wouldn't
-  // be able to display something meaningful in the UI in those cases anyway.
-  const PowerPolicyController::Action idle_action =
-      static_cast<PowerPolicyController::Action>(
-          prefs_->GetInteger(ash::prefs::kPowerAcIdleAction));
-  IdleBehavior idle_behavior = IdleBehavior::OTHER;
-  if (idle_action == PowerPolicyController::ACTION_SUSPEND) {
-    idle_behavior = IdleBehavior::DISPLAY_OFF_SLEEP;
-  } else if (idle_action == PowerPolicyController::ACTION_DO_NOTHING) {
-    idle_behavior =
-        (prefs_->GetInteger(ash::prefs::kPowerAcScreenOffDelayMs) > 0
-             ? IdleBehavior::DISPLAY_OFF
-             : IdleBehavior::DISPLAY_ON);
-  }
-
-  const bool idle_controlled =
-      prefs_->IsManagedPreference(ash::prefs::kPowerAcIdleAction) ||
-      prefs_->IsManagedPreference(ash::prefs::kPowerAcScreenDimDelayMs) ||
-      prefs_->IsManagedPreference(ash::prefs::kPowerAcScreenOffDelayMs) ||
-      prefs_->IsManagedPreference(ash::prefs::kPowerAcScreenLockDelayMs) ||
-      prefs_->IsManagedPreference(ash::prefs::kPowerBatteryIdleAction) ||
-      prefs_->IsManagedPreference(ash::prefs::kPowerBatteryScreenDimDelayMs) ||
-      prefs_->IsManagedPreference(ash::prefs::kPowerBatteryScreenOffDelayMs) ||
-      prefs_->IsManagedPreference(ash::prefs::kPowerBatteryScreenLockDelayMs);
+  const PowerHandler::IdleBehaviorInfo ac_idle_info =
+      GetAllowedIdleBehaviors(PowerSource::kAc);
+  const PowerHandler::IdleBehaviorInfo battery_idle_info =
+      GetAllowedIdleBehaviors(PowerSource::kBattery);
 
   const PowerPolicyController::Action lid_closed_behavior =
       static_cast<PowerPolicyController::Action>(
@@ -371,23 +373,37 @@
   const bool has_lid = lid_state_ != PowerManagerClient::LidState::NOT_PRESENT;
 
   // Don't notify the UI if nothing changed.
-  if (!force && idle_behavior == last_idle_behavior_ &&
-      idle_controlled == last_idle_controlled_ &&
+  if (!force && ac_idle_info == last_ac_idle_info_ &&
+      battery_idle_info == last_battery_idle_info_ &&
       lid_closed_behavior == last_lid_closed_behavior_ &&
       lid_closed_controlled == last_lid_closed_controlled_ &&
-      has_lid == last_has_lid_)
+      has_lid == last_has_lid_) {
     return;
+  }
 
   base::DictionaryValue dict;
-  dict.SetInteger(kIdleBehaviorKey, static_cast<int>(idle_behavior));
-  dict.SetBoolean(kIdleControlledKey, idle_controlled);
+  base::Value* list = dict.SetKey(kPossibleAcIdleBehaviorsKey,
+                                  base::Value(base::Value::Type::LIST));
+  for (auto idle_behavior : ac_idle_info.possible_behaviors)
+    list->Append(static_cast<int>(idle_behavior));
+
+  list = dict.SetKey(kPossibleBatteryIdleBehaviorsKey,
+                     base::Value(base::Value::Type::LIST));
+  for (auto idle_behavior : battery_idle_info.possible_behaviors)
+    list->Append(static_cast<int>(idle_behavior));
+  dict.SetInteger(kCurrentAcIdleBehaviorKey,
+                  static_cast<int>(ac_idle_info.current_behavior));
+  dict.SetInteger(kCurrentBatteryIdleBehaviorKey,
+                  static_cast<int>(battery_idle_info.current_behavior));
   dict.SetInteger(kLidClosedBehaviorKey, lid_closed_behavior);
+  dict.SetBoolean(kAcIdleManagedKey, ac_idle_info.is_managed);
+  dict.SetBoolean(kBatteryIdleManagedKey, battery_idle_info.is_managed);
   dict.SetBoolean(kLidClosedControlledKey, lid_closed_controlled);
   dict.SetBoolean(kHasLidKey, has_lid);
   FireWebUIListener(kPowerManagementSettingsChangedName, dict);
 
-  last_idle_behavior_ = idle_behavior;
-  last_idle_controlled_ = idle_controlled;
+  last_ac_idle_info_ = ac_idle_info;
+  last_battery_idle_info_ = battery_idle_info;
   last_lid_closed_behavior_ = lid_closed_behavior;
   last_lid_closed_controlled_ = lid_closed_controlled;
   last_has_lid_ = has_lid;
@@ -401,5 +417,159 @@
   SendPowerManagementSettings(false /* force */);
 }
 
+PowerHandler::IdleBehaviorInfo PowerHandler::GetAllowedIdleBehaviors(
+    PowerSource power_source) {
+  const char* idle_pref = power_source == PowerSource::kAc
+                              ? ash::prefs::kPowerAcIdleAction
+                              : ash::prefs::kPowerBatteryIdleAction;
+  const char* screen_off_delay_pref =
+      power_source == PowerSource::kAc
+          ? ash::prefs::kPowerAcScreenOffDelayMs
+          : ash::prefs::kPowerBatteryScreenOffDelayMs;
+
+  std::set<IdleBehavior> possible_behaviors;
+  IdleBehavior current_idle_behavior;
+
+  // If idle action is managed and set to suspend, only possible idle
+  // behaviour is sleep with display off.
+  if (prefs_->IsManagedPreference(idle_pref) &&
+      prefs_->GetInteger(idle_pref) == PowerPolicyController::ACTION_SUSPEND) {
+    current_idle_behavior = IdleBehavior::DISPLAY_OFF_SLEEP;
+    possible_behaviors.insert(IdleBehavior::DISPLAY_OFF_SLEEP);
+    return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+                            IsIdleManaged(power_source));
+  }
+
+  // If idle action is managed and set to SHUT_DOWN/STOP_SESSION, only
+  // possible idle behaviour is other.
+  if (prefs_->IsManagedPreference(idle_pref) &&
+      (prefs_->GetInteger(idle_pref) ==
+           PowerPolicyController::ACTION_STOP_SESSION ||
+       prefs_->GetInteger(idle_pref) ==
+           PowerPolicyController::ACTION_SHUT_DOWN)) {
+    current_idle_behavior = IdleBehavior::OTHER;
+    possible_behaviors.insert(IdleBehavior::OTHER);
+    return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+                            IsIdleManaged(power_source));
+  }
+
+  // Note that after this point |idle_pref| should either be:
+  //    1. Not managed.
+  //    2. Or managed and set to
+  //    PowerPolicyController::ACTION_DO_NOTHING.
+  DCHECK(!prefs_->IsManagedPreference(idle_pref) ||
+         (prefs_->GetInteger(idle_pref) ==
+          PowerPolicyController::ACTION_DO_NOTHING));
+
+  // If screen off delay is managed and set to a value greater than 0
+  // and
+  //   1. If idle action is managed and set to DO_NOTHING, only
+  //      possible idle behavior is DISPLAY_OFF.
+  //   2. If idle action is not managed then possible idle options
+  //      are DiSPLAY_OFF and DISPLAY_OFF_SLEEP
+  if (prefs_->IsManagedPreference(screen_off_delay_pref) &&
+      prefs_->GetInteger(screen_off_delay_pref) > 0) {
+    if (prefs_->IsManagedPreference(idle_pref) &&
+        prefs_->GetInteger(idle_pref) ==
+            PowerPolicyController::ACTION_DO_NOTHING) {
+      current_idle_behavior = IdleBehavior::DISPLAY_OFF;
+      possible_behaviors.insert(IdleBehavior::DISPLAY_OFF);
+      return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+                              IsIdleManaged(power_source));
+    }
+
+    possible_behaviors.insert(IdleBehavior::DISPLAY_OFF);
+    possible_behaviors.insert(IdleBehavior::DISPLAY_OFF_SLEEP);
+    // Set the current default option based on the current idle action.
+    const PowerPolicyController::Action idle_action =
+        static_cast<PowerPolicyController::Action>(
+            prefs_->GetInteger(idle_pref));
+
+    if (idle_action == PowerPolicyController::ACTION_SUSPEND)
+      current_idle_behavior = IdleBehavior::DISPLAY_OFF_SLEEP;
+    else
+      current_idle_behavior = IdleBehavior::DISPLAY_OFF;
+    return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+                            IsIdleManaged(power_source));
+  }
+
+  // If idle action is managed and set to DO_NOTHING, and
+  //   1. If screen off delay is also managed (and set to 0), only
+  //   possible idle
+  //      action is DISPLAY_ON.
+  //   2. If AC screen off delay is not managed, possible idle actions
+  //      are DISPLAY_ON && DISPLAY_OFF.
+  if (prefs_->IsManagedPreference(idle_pref) &&
+      prefs_->GetInteger(idle_pref) ==
+          PowerPolicyController::ACTION_DO_NOTHING) {
+    if (prefs_->IsManagedPreference(screen_off_delay_pref)) {
+      // Note that we reach here only when screen off delays are
+      // set by enterprise policy to 0 to prevent display from turning
+      // off.
+      DCHECK(prefs_->GetInteger(screen_off_delay_pref) == 0);
+      current_idle_behavior = IdleBehavior::DISPLAY_ON;
+      possible_behaviors.insert(IdleBehavior::DISPLAY_ON);
+      return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+                              IsIdleManaged(power_source));
+    }
+    possible_behaviors.insert(IdleBehavior::DISPLAY_ON);
+    possible_behaviors.insert(IdleBehavior::DISPLAY_OFF);
+    // Set the current default option based on the current screen off
+    // delay.
+    current_idle_behavior = prefs_->GetInteger(screen_off_delay_pref) > 0
+                                ? IdleBehavior::DISPLAY_OFF
+                                : IdleBehavior::DISPLAY_ON;
+    return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+                            IsIdleManaged(power_source));
+  }
+
+  // Looks like we did not find enterprise policy restricitng the idle
+  // options. So add all three idle options to what user can select
+  // from.
+  possible_behaviors.insert(IdleBehavior::DISPLAY_ON);
+  possible_behaviors.insert(IdleBehavior::DISPLAY_OFF);
+  possible_behaviors.insert(IdleBehavior::DISPLAY_OFF_SLEEP);
+
+  // Infer the idle behavior based on the current idle action
+  // (determining whether we'll sleep eventually or not) and the AC
+  // screen-off delay.
+  const PowerPolicyController::Action idle_action =
+      static_cast<PowerPolicyController::Action>(prefs_->GetInteger(idle_pref));
+
+  if (idle_action == PowerPolicyController::ACTION_SUSPEND) {
+    current_idle_behavior = IdleBehavior::DISPLAY_OFF_SLEEP;
+  } else if (idle_action == PowerPolicyController::ACTION_DO_NOTHING) {
+    current_idle_behavior = (prefs_->GetInteger(screen_off_delay_pref) > 0
+                                 ? IdleBehavior::DISPLAY_OFF
+                                 : IdleBehavior::DISPLAY_ON);
+  } else {
+    current_idle_behavior = IdleBehavior::OTHER;
+    possible_behaviors.insert(IdleBehavior::OTHER);
+  }
+
+  return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+                          IsIdleManaged(power_source));
+}
+
+bool PowerHandler::IsIdleManaged(PowerSource power_source) {
+  switch (power_source) {
+    case PowerSource::kAc:
+      return prefs_->IsManagedPreference(ash::prefs::kPowerAcIdleAction) ||
+             prefs_->IsManagedPreference(
+                 ash::prefs::kPowerAcScreenDimDelayMs) ||
+             prefs_->IsManagedPreference(
+                 ash::prefs::kPowerAcScreenOffDelayMs) ||
+             prefs_->IsManagedPreference(ash::prefs::kPowerAcScreenLockDelayMs);
+    case PowerSource::kBattery:
+      return prefs_->IsManagedPreference(ash::prefs::kPowerBatteryIdleAction) ||
+             prefs_->IsManagedPreference(
+                 ash::prefs::kPowerBatteryScreenDimDelayMs) ||
+             prefs_->IsManagedPreference(
+                 ash::prefs::kPowerBatteryScreenOffDelayMs) ||
+             prefs_->IsManagedPreference(
+                 ash::prefs::kPowerBatteryScreenLockDelayMs);
+  }
+}
+
 }  // namespace settings
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
index d55a3944..1d125b0 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_POWER_HANDLER_H_
 
 #include <memory>
+#include <set>
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -22,7 +23,7 @@
 namespace base {
 class ListValue;
 class TimeTicks;
-}
+}  // namespace base
 
 namespace chromeos {
 namespace settings {
@@ -43,8 +44,12 @@
 
   // WebUI message name and dictionary keys. Shared with tests.
   static const char kPowerManagementSettingsChangedName[];
-  static const char kIdleBehaviorKey[];
-  static const char kIdleControlledKey[];
+  static const char kPossibleAcIdleBehaviorsKey[];
+  static const char kPossibleBatteryIdleBehaviorsKey[];
+  static const char kAcIdleManagedKey[];
+  static const char kBatteryIdleManagedKey[];
+  static const char kCurrentAcIdleBehaviorKey[];
+  static const char kCurrentBatteryIdleBehaviorKey[];
   static const char kLidClosedBehaviorKey[];
   static const char kLidClosedControlledKey[];
   static const char kHasLidKey[];
@@ -56,7 +61,9 @@
     ~TestAPI();
 
     void RequestPowerManagementSettings();
-    void SetIdleBehavior(IdleBehavior behavior);
+    // Sets AC idle behavior to |behavior| if |when_on_ac| is true. Otherwise
+    // sets battery idle behavior to |behavior|.
+    void SetIdleBehavior(IdleBehavior behavior, bool when_on_ac);
     void SetLidClosedBehavior(PowerPolicyController::Action behavior);
 
    private:
@@ -80,6 +87,33 @@
                         const base::TimeTicks& timestamp) override;
 
  private:
+  enum class PowerSource { kAc, kBattery };
+
+  // Struct holding possible idle behaviors and the current behavior while
+  // charging/when on battery.
+  struct IdleBehaviorInfo {
+    IdleBehaviorInfo();
+    IdleBehaviorInfo(const std::set<IdleBehavior>& possible_behaviors,
+                     const IdleBehavior& current_behavior,
+                     const bool is_managed);
+
+    IdleBehaviorInfo(const IdleBehaviorInfo& o);
+    ~IdleBehaviorInfo();
+
+    bool operator==(const IdleBehaviorInfo& o) const {
+      return (possible_behaviors == o.possible_behaviors &&
+              current_behavior == o.current_behavior &&
+              is_managed == o.is_managed);
+    }
+
+    // All possible idle behaviors.
+    std::set<IdleBehavior> possible_behaviors;
+    // Current idle behavior.
+    IdleBehavior current_behavior = IdleBehavior::DISPLAY_OFF_SLEEP;
+    // Whether enterpise policy manages idle behavior.
+    bool is_managed = false;
+  };
+
   // Handler to request updating the power status.
   void HandleUpdatePowerStatus(const base::ListValue* args);
 
@@ -109,7 +143,16 @@
   void OnGotSwitchStates(
       base::Optional<PowerManagerClient::SwitchStates> result);
 
-  PrefService* prefs_;              // Not owned.
+  // Returns all possible idle behaviors (that a user can choose from) and
+  // current idle behavior based on enterprise policy and other factors when on
+  // |power_source|.
+  IdleBehaviorInfo GetAllowedIdleBehaviors(PowerSource power_source);
+
+  // Returns true if the enterprise policy enforces any settings that can impact
+  // the idle behavior of the device when on |power_source|.
+  bool IsIdleManaged(PowerSource power_source);
+
+  PrefService* const prefs_;
 
   // Used to watch power management prefs for changes so the UI can be notified.
   std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
@@ -123,10 +166,10 @@
   // Last values sent by SendPowerManagementSettings(), cached here so
   // SendPowerManagementSettings() can avoid spamming the UI after this class
   // changes multiple prefs at once.
-  IdleBehavior last_idle_behavior_ = IdleBehavior::DISPLAY_OFF_SLEEP;
+  IdleBehaviorInfo last_ac_idle_info_;
+  IdleBehaviorInfo last_battery_idle_info_;
   PowerPolicyController::Action last_lid_closed_behavior_ =
       PowerPolicyController::ACTION_SUSPEND;
-  bool last_idle_controlled_ = false;
   bool last_lid_closed_controlled_ = false;
   bool last_has_lid_ = true;
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
index c27e55cb..c928ccd2 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h"
-
 #include <memory>
+#include <set>
 #include <utility>
 
 #include "ash/public/cpp/ash_pref_names.h"
@@ -13,6 +12,7 @@
 #include "base/run_loop.h"
 #include "base/values.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
@@ -24,8 +24,8 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using testing::Return;
 using testing::_;
+using testing::Return;
 
 namespace chromeos {
 namespace settings {
@@ -48,6 +48,34 @@
 
 class PowerHandlerTest : public InProcessBrowserTest {
  protected:
+  struct DevicePowerSettings {
+    // Initialize with initial settings.
+    DevicePowerSettings() {
+      possible_ac_behaviors.insert(
+          PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP);
+      possible_ac_behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_OFF);
+      possible_ac_behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_ON);
+      possible_battery_behaviors.insert(
+          PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP);
+      possible_battery_behaviors.insert(
+          PowerHandler::IdleBehavior::DISPLAY_OFF);
+      possible_battery_behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_ON);
+    }
+
+    std::set<PowerHandler::IdleBehavior> possible_ac_behaviors;
+    std::set<PowerHandler::IdleBehavior> possible_battery_behaviors;
+    PowerHandler::IdleBehavior current_ac_behavior =
+        PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP;
+    PowerHandler::IdleBehavior current_battery_behavior =
+        PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP;
+    bool ac_idle_managed = false;
+    bool battery_idle_managed = false;
+    PowerPolicyController::Action lid_closed_behavior =
+        PowerPolicyController::ACTION_SUSPEND;
+    bool lid_closed_controlled = false;
+    bool has_lid = true;
+  };
+
   PowerHandlerTest() = default;
   ~PowerHandlerTest() override = default;
 
@@ -99,23 +127,32 @@
     return std::string();
   }
 
-  // Returns a string for the given settings that can be compared against the
-  // output of GetLastSettingsChangedMessage().
-  std::string CreateSettingsChangedString(
-      PowerHandler::IdleBehavior idle_behavior,
-      bool idle_controlled,
-      PowerPolicyController::Action lid_closed_behavior,
-      bool lid_closed_controlled,
-      bool has_lid) {
+  // Returns a string for the given |settings|. Used to verify expected
+  // settings are sent to the UI.
+  std::string ToString(const DevicePowerSettings& settings) {
     base::DictionaryValue dict;
-    dict.SetInteger(PowerHandler::kIdleBehaviorKey,
-                    static_cast<int>(idle_behavior));
-    dict.SetBoolean(PowerHandler::kIdleControlledKey, idle_controlled);
-    dict.SetInteger(PowerHandler::kLidClosedBehaviorKey, lid_closed_behavior);
-    dict.SetBoolean(PowerHandler::kLidClosedControlledKey,
-                    lid_closed_controlled);
-    dict.SetBoolean(PowerHandler::kHasLidKey, has_lid);
+    base::Value* list = dict.SetKey(PowerHandler::kPossibleAcIdleBehaviorsKey,
+                                    base::Value(base::Value::Type::LIST));
+    for (auto idle_behavior : settings.possible_ac_behaviors)
+      list->Append(static_cast<int>(idle_behavior));
 
+    list = dict.SetKey(PowerHandler::kPossibleBatteryIdleBehaviorsKey,
+                       base::Value(base::Value::Type::LIST));
+    for (auto idle_behavior : settings.possible_battery_behaviors)
+      list->Append(static_cast<int>(idle_behavior));
+
+    dict.SetInteger(PowerHandler::kCurrentAcIdleBehaviorKey,
+                    static_cast<int>(settings.current_ac_behavior));
+    dict.SetInteger(PowerHandler::kCurrentBatteryIdleBehaviorKey,
+                    static_cast<int>(settings.current_battery_behavior));
+    dict.SetBoolean(PowerHandler::kAcIdleManagedKey, settings.ac_idle_managed);
+    dict.SetBoolean(PowerHandler::kBatteryIdleManagedKey,
+                    settings.battery_idle_managed);
+    dict.SetInteger(PowerHandler::kLidClosedBehaviorKey,
+                    settings.lid_closed_behavior);
+    dict.SetBoolean(PowerHandler::kLidClosedControlledKey,
+                    settings.lid_closed_controlled);
+    dict.SetBoolean(PowerHandler::kHasLidKey, settings.has_lid);
     std::string out;
     EXPECT_TRUE(base::JSONWriter::Write(dict, &out));
     return out;
@@ -129,6 +166,12 @@
     return GetPrefs()->GetInteger(name);
   }
 
+  // Trigger power pref managed change.
+  void UpdateChromePolicy(policy::PolicyMap* policy_map) {
+    provider_.UpdateChromePolicy(*policy_map);
+    base::RunLoop().RunUntilIdle();
+  }
+
   // Sets a policy update which will cause power pref managed change.
   void SetPolicyForPolicyKey(policy::PolicyMap* policy_map,
                              const std::string& policy_key,
@@ -136,8 +179,7 @@
     policy_map->Set(policy_key, policy::POLICY_LEVEL_MANDATORY,
                     policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
                     std::move(value), nullptr);
-    provider_.UpdateChromePolicy(*policy_map);
-    base::RunLoop().RunUntilIdle();
+    UpdateChromePolicy(policy_map);
   }
 
   std::unique_ptr<TestPowerHandler> handler_;
@@ -154,122 +196,192 @@
 // Verifies that settings are sent to WebUI when requested.
 IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendInitialSettings) {
   test_api_->RequestPowerManagementSettings();
-  EXPECT_EQ(
-      CreateSettingsChangedString(
-          PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
-          false /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
-          false /* lid_closed_controlled */, true /* has_lid */),
-      GetLastSettingsChangedMessage());
+  // Initialized to initial settings.
+  DevicePowerSettings settings;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
 }
 
 // Verifies that WebUI receives updated settings when the lid state changes.
 IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendSettingsForLidStateChanges) {
   chromeos::FakePowerManagerClient::Get()->SetLidState(
       PowerManagerClient::LidState::NOT_PRESENT, base::TimeTicks());
-  EXPECT_EQ(
-      CreateSettingsChangedString(
-          PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
-          false /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
-          false /* lid_closed_controlled */, false /* has_lid */),
-      GetLastSettingsChangedMessage());
+
+  DevicePowerSettings settings;
+  settings.has_lid = false;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
 
   chromeos::FakePowerManagerClient::Get()->SetLidState(
       PowerManagerClient::LidState::OPEN, base::TimeTicks());
-  EXPECT_EQ(
-      CreateSettingsChangedString(
-          PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
-          false /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
-          false /* lid_closed_controlled */, true /* has_lid */),
-      GetLastSettingsChangedMessage());
+  settings.has_lid = true;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
 }
 
-// Verifies that when various prefs are controlled, the corresponding settings
-// are reported as controlled to WebUI.
+// Verifies that when various prefs are controlled, the corresponding
+// settings are reported as controlled/managed to WebUI.
 IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendSettingsForControlledPrefs) {
   policy::PolicyMap policy_map;
-  // Making an arbitrary delay pref managed should result in the idle setting
-  // being reported as controlled.
+  // Making an arbitrary AC delay pref managed should result in the AC idle
+  // setting being reported as managed.
   SetPolicyForPolicyKey(&policy_map, policy::key::kScreenDimDelayAC,
                         std::make_unique<base::Value>(10000));
-  EXPECT_EQ(
-      CreateSettingsChangedString(
-          PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
-          true /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
-          false /* lid_closed_controlled */, true /* has_lid */),
-      GetLastSettingsChangedMessage());
+  DevicePowerSettings settings;
+  settings.ac_idle_managed = true;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+
+  // Ditto for battery delay pref managed.
+  SetPolicyForPolicyKey(&policy_map, policy::key::kScreenDimDelayBattery,
+                        std::make_unique<base::Value>(10000));
+  settings.battery_idle_managed = true;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
 
   // Ditto for making the lid action pref managed.
   SetPolicyForPolicyKey(
       &policy_map, policy::key::kLidCloseAction,
       std::make_unique<base::Value>(PowerPolicyController::ACTION_SUSPEND));
-  EXPECT_EQ(
-      CreateSettingsChangedString(
-          PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
-          true /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
-          true /* lid_closed_controlled */, true /* has_lid */),
-      GetLastSettingsChangedMessage());
+  settings.lid_closed_controlled = true;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
 }
 
-// Verifies that idle-related prefs are distilled into the proper WebUI
-// settings.
+// Verifies that idle-related prefs (when not managed by enterpise policy)
+// are distilled into the proper WebUI settings.
 IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendIdleSettingForPrefChanges) {
-  // Set a do-nothing idle action and a nonzero screen-off delay.
+  // Initial power settings.
+  DevicePowerSettings settings;
+  // Set a AC do-nothing idle action and a AC nonzero screen-off delay. User
+  // should see all three options (DISPLAY_ON, DISPLAY_OFF and
+  // DISPLAY_OFF_SLEEP) and the selected setting when on AC should be set to
+  // DISPLAY_OFF.
   GetPrefs()->Set(ash::prefs::kPowerAcIdleAction,
                   base::Value(PowerPolicyController::ACTION_DO_NOTHING));
   GetPrefs()->Set(ash::prefs::kPowerAcScreenOffDelayMs, base::Value(10000));
-  EXPECT_EQ(CreateSettingsChangedString(PowerHandler::IdleBehavior::DISPLAY_OFF,
-                                        false /* idle_controlled */,
-                                        PowerPolicyController::ACTION_SUSPEND,
-                                        false /* lid_closed_controlled */,
-                                        true /* has_lid */),
-            GetLastSettingsChangedMessage());
 
-  // Now set the delay to zero and check that the setting goes to "display on".
-  GetPrefs()->Set(ash::prefs::kPowerAcScreenOffDelayMs, base::Value(0));
-  EXPECT_EQ(CreateSettingsChangedString(PowerHandler::IdleBehavior::DISPLAY_ON,
-                                        false /* idle_controlled */,
-                                        PowerPolicyController::ACTION_SUSPEND,
-                                        false /* lid_closed_controlled */,
-                                        true /* has_lid */),
-            GetLastSettingsChangedMessage());
+  // Current AC idle behavior should be DISPLAY_OFF.
+  settings.current_ac_behavior = PowerHandler::IdleBehavior::DISPLAY_OFF;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+
+  // Now set the battery screen off delay to zero along with battery do-nothing
+  // idle action and check that the selected setting goes to "display on" when
+  // on battery.
+  GetPrefs()->Set(ash::prefs::kPowerBatteryIdleAction,
+                  base::Value(PowerPolicyController::ACTION_DO_NOTHING));
+  GetPrefs()->Set(ash::prefs::kPowerBatteryScreenOffDelayMs, base::Value(0));
+
+  // Current battery idle behavior should be DISPLAY_ON.
+  settings.current_battery_behavior = PowerHandler::IdleBehavior::DISPLAY_ON;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
 
   // Other idle actions should result in an "other" setting.
   GetPrefs()->Set(ash::prefs::kPowerAcIdleAction,
                   base::Value(PowerPolicyController::ACTION_STOP_SESSION));
-  EXPECT_EQ(CreateSettingsChangedString(
-                PowerHandler::IdleBehavior::OTHER, false /* idle_controlled */,
-                PowerPolicyController::ACTION_SUSPEND,
-                false /* lid_closed_controlled */, true /* has_lid */),
-            GetLastSettingsChangedMessage());
+  // Current AC idle behavior should be OTHER.
+  settings.current_ac_behavior = PowerHandler::IdleBehavior::OTHER;
+  // Possible AC idle behaviors should include OTHER too.
+  settings.possible_ac_behaviors.insert(PowerHandler::IdleBehavior::OTHER);
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+}
+
+// Verifies that idle-related prefs when managed by enterpise policy are
+// distilled into the proper WebUI settings.
+IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendManagedIdleSettingForPrefChanges) {
+  policy::PolicyMap policy_map;
+  // Set Enterpise policy that forces AC idle action to suspend. Only possible
+  // AC idle option visible to the user should be DISPLAY_OFF_SLEEP and the
+  // current should also be set to same.
+  SetPolicyForPolicyKey(&policy_map, policy::key::kIdleActionAC,
+                        std::make_unique<base::Value>(
+                            chromeos::PowerPolicyController::ACTION_SUSPEND));
+  DevicePowerSettings settings;
+  std::set<PowerHandler::IdleBehavior> behaviors;
+  behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP);
+  settings.possible_ac_behaviors = behaviors;
+  settings.ac_idle_managed = true;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+
+  // Set Enterpise policy that forces battery idle action to Shutdown. Only
+  // possible battery idle option visible to the user then should be OTHER and
+  // the default should also be set to same.
+  SetPolicyForPolicyKey(&policy_map, policy::key::kIdleActionBattery,
+                        std::make_unique<base::Value>(
+                            chromeos::PowerPolicyController::ACTION_SHUT_DOWN));
+  behaviors.clear();
+  behaviors.insert(PowerHandler::IdleBehavior::OTHER);
+  settings.possible_battery_behaviors = behaviors;
+  settings.current_battery_behavior = PowerHandler::IdleBehavior::OTHER;
+  settings.battery_idle_managed = true;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+  // Erase battery idle action.
+  policy_map.Erase(policy::key::kIdleActionBattery);
+
+  // Set battery idle action to DO_NOTHING in Enterpise policy. The user then
+  // should not see DISPLAY_OFF_SLEEP in available options.
+  SetPolicyForPolicyKey(
+      &policy_map, policy::key::kIdleActionBattery,
+      std::make_unique<base::Value>(
+          chromeos::PowerPolicyController::ACTION_DO_NOTHING));
+  behaviors.clear();
+  behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_OFF);
+  behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_ON);
+  settings.possible_battery_behaviors = behaviors;
+  settings.current_battery_behavior = PowerHandler::IdleBehavior::DISPLAY_OFF;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+
+  // Set battery screen delay in Enterprise policy on top of DO_NOTHING idle
+  // action. The user should see only see DISPLAY_OFF as the possible battery
+  // idle action.
+  SetPolicyForPolicyKey(&policy_map, policy::key::kScreenOffDelayBattery,
+                        std::make_unique<base::Value>(10000));
+  behaviors.clear();
+  behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_OFF);
+  settings.possible_battery_behaviors = behaviors;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+
+  // Now stop enforcing battery idle action (to DO_NOTHING) in enterprise
+  // policy. The user should see DISPLAY_OFF and DISPLAY_OFF_SLEEP as
+  // the possible battery idle actions.
+  policy_map.Erase(policy::key::kIdleActionBattery);
+  UpdateChromePolicy(&policy_map);
+  settings.possible_battery_behaviors.insert(
+      PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP);
+  settings.current_battery_behavior =
+      PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
 }
 
 // Verifies that the lid-closed pref's value is sent directly to WebUI.
 IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendLidSettingForPrefChanges) {
   GetPrefs()->Set(ash::prefs::kPowerLidClosedAction,
                   base::Value(PowerPolicyController::ACTION_SHUT_DOWN));
-  EXPECT_EQ(
-      CreateSettingsChangedString(
-          PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
-          false /* idle_controlled */, PowerPolicyController::ACTION_SHUT_DOWN,
-          false /* lid_closed_controlled */, true /* has_lid */),
-      GetLastSettingsChangedMessage());
+  DevicePowerSettings settings;
+  settings.lid_closed_behavior = PowerPolicyController::ACTION_SHUT_DOWN;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
 
   GetPrefs()->Set(ash::prefs::kPowerLidClosedAction,
                   base::Value(PowerPolicyController::ACTION_STOP_SESSION));
-  EXPECT_EQ(CreateSettingsChangedString(
-                PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
-                false /* idle_controlled */,
-                PowerPolicyController::ACTION_STOP_SESSION,
-                false /* lid_closed_controlled */, true /* has_lid */),
-            GetLastSettingsChangedMessage());
+  settings.lid_closed_behavior = PowerPolicyController::ACTION_STOP_SESSION;
+  EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
 }
 
 // Verifies that requests from WebUI to update the idle behavior update prefs
 // appropriately.
 IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SetIdleBehavior) {
-  // Request the "Keep display on" setting and check that prefs are set
+  // Request the "Keep display on" AC setting and check that prefs are set
   // appropriately.
-  test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON);
+  test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON,
+                             true /* is_ac */);
+  EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
+            GetIntPref(ash::prefs::kPowerAcIdleAction));
+  EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
+  EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
+  EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
+  EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryIdleAction));
+  EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenDimDelayMs));
+  EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenOffDelayMs));
+  EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenLockDelayMs));
+
+  // "Turn off display" battery setting should set the battery idle pref but
+  // clear the battery screen delays.
+  test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF,
+                             false /* is_battery */);
   EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
             GetIntPref(ash::prefs::kPowerAcIdleAction));
   EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
@@ -277,32 +389,22 @@
   EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
   EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
             GetIntPref(ash::prefs::kPowerBatteryIdleAction));
-  EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerBatteryScreenDimDelayMs));
-  EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerBatteryScreenOffDelayMs));
-  EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerBatteryScreenLockDelayMs));
-
-  // "Turn off display" should set the idle prefs but clear the screen
-  // delays.
-  test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF);
-  EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
-            GetIntPref(ash::prefs::kPowerAcIdleAction));
-  EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
-  EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
-  EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
-  EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
-            GetIntPref(ash::prefs::kPowerBatteryIdleAction));
   EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenDimDelayMs));
   EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenOffDelayMs));
   EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenLockDelayMs));
 
-  // Now switch to the "Keep display on" setting (to set the prefs again) and
-  // check that the "Turn off display and sleep" setting clears all the prefs.
-  test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON);
-  test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP);
-  EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcIdleAction));
-  EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
-  EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
-  EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
+  // Now switch to the "Keep display on" battery setting (to set the prefs
+  // again) and check that the "Turn off display and sleep" battery setting
+  // clears all the battery prefs.
+  test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON,
+                             false /* is_battery */);
+  test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
+                             false /* is_battery */);
+  EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
+            GetIntPref(ash::prefs::kPowerAcIdleAction));
+  EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
+  EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
+  EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
   EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryIdleAction));
   EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenDimDelayMs));
   EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenOffDelayMs));
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc
index 91ec1d9..fcde235 100644
--- a/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc
@@ -1260,6 +1260,14 @@
        IDS_SETTINGS_POWER_SOURCE_LOW_POWER_CHARGER},
       {"calculatingPower", IDS_SETTINGS_POWER_SOURCE_CALCULATING},
       {"powerIdleLabel", IDS_SETTINGS_POWER_IDLE_LABEL},
+      {"powerIdleWhileChargingLabel",
+       IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_LABEL},
+      {"powerIdleWhileChargingAriaLabel",
+       IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_ARIA_LABEL},
+      {"powerIdleWhileOnBatteryLabel",
+       IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_LABEL},
+      {"powerIdleWhileOnBatteryAriaLabel",
+       IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_ARIA_LABEL},
       {"powerIdleDisplayOffSleep", IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF_SLEEP},
       {"powerIdleDisplayOff", IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF},
       {"powerIdleDisplayOn", IDS_SETTINGS_POWER_IDLE_DISPLAY_ON},
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
index fefd823..d6f8325 100644
--- a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
@@ -52,6 +52,7 @@
 #include "chrome/browser/ui/webui/settings/chromeos/crostini_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/date_time_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/device_display_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h"
@@ -321,6 +322,11 @@
     web_ui()->AddMessageHandler(std::move(kerberos_accounts_handler));
   }
 
+  if (ash::features::IsDisplayIdentificationEnabled()) {
+    web_ui()->AddMessageHandler(
+        std::make_unique<chromeos::settings::DisplayHandler>());
+  }
+
   web_ui()->AddMessageHandler(
       std::make_unique<chromeos::settings::KeyboardHandler>());
 
diff --git a/chrome/browser/web_applications/components/install_finalizer.h b/chrome/browser/web_applications/components/install_finalizer.h
index 628e895..9168b69 100644
--- a/chrome/browser/web_applications/components/install_finalizer.h
+++ b/chrome/browser/web_applications/components/install_finalizer.h
@@ -94,9 +94,6 @@
                            bool shortcut_created,
                            content::WebContents* web_contents);
 
-  virtual bool CanRevealAppShim() const = 0;
-  virtual void RevealAppShim(const AppId& app_id) = 0;
-
   void SetSubsystems(AppRegistrar* registrar, WebAppUiManager* ui_manager);
 
   virtual ~InstallFinalizer() = default;
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_mac.h b/chrome/browser/web_applications/components/web_app_shortcut_mac.h
index 68d99a4..f2f3260 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut_mac.h
+++ b/chrome/browser/web_applications/components/web_app_shortcut_mac.h
@@ -106,7 +106,7 @@
                        std::vector<base::FilePath>* updated_paths);
 
   // Show the bundle we just generated in the Finder.
-  virtual void RevealAppShimInFinder() const;
+  virtual void RevealAppShimInFinder(const base::FilePath& app_path) const;
 
  protected:
   virtual std::vector<base::FilePath> GetAppBundlesByIdUnsorted() const;
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_mac.mm b/chrome/browser/web_applications/components/web_app_shortcut_mac.mm
index 51484d29..2f4d75e 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut_mac.mm
+++ b/chrome/browser/web_applications/components/web_app_shortcut_mac.mm
@@ -934,7 +934,7 @@
   if (!UpdateShortcuts(true /* create_if_needed */, &updated_app_paths))
     return false;
   if (creation_reason == SHORTCUT_CREATION_BY_USER)
-    RevealAppShimInFinder();
+    RevealAppShimInFinder(updated_app_paths[0]);
   return true;
 }
 
@@ -1198,33 +1198,13 @@
   return info_->url.is_valid();
 }
 
-void WebAppShortcutCreator::RevealAppShimInFinder() const {
-  // Note that RevealAppShimInFinder is called immediately after requesting to
-  // build the app shim. This almost always happens before the app shim has
-  // completed building (and so we just open the Chrome apps folder).
-
-  // Check if the app shim exists.
-  auto app_paths = GetAppBundlesById();
-  if (!app_paths.empty()) {
-    base::FilePath app_path = app_paths.front();
-    // Use selectFile to show the contents of parent directory with the app
-    // shim selected.
-    [[NSWorkspace sharedWorkspace]
-                      selectFile:base::mac::FilePathToNSString(app_path)
-        inFileViewerRootedAtPath:@""];
-    return;
-  }
-
-  // Otherwise, open the Chrome apps folder, in the hopes that the app shim is
-  // being asynchronously created there.
-  base::FilePath apps_path = GetChromeAppsFolder();
-  if (!base::PathExists(apps_path))
-    return;
-
-  // Since |app_path| is a directory, use openFile to show the contents of
-  // that directory in Finder.
+void WebAppShortcutCreator::RevealAppShimInFinder(
+    const base::FilePath& app_path) const {
+  // Use selectFile to show the contents of parent directory with the app
+  // shim selected.
   [[NSWorkspace sharedWorkspace]
-      openFile:base::mac::FilePathToNSString(apps_path)];
+                    selectFile:base::mac::FilePathToNSString(app_path)
+      inFileViewerRootedAtPath:@""];
 }
 
 void LaunchShim(LaunchShimUpdateBehavior update_behavior,
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_mac_unittest.mm b/chrome/browser/web_applications/components/web_app_shortcut_mac_unittest.mm
index af1528d..f6febe3 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut_mac_unittest.mm
+++ b/chrome/browser/web_applications/components/web_app_shortcut_mac_unittest.mm
@@ -50,7 +50,7 @@
       : WebAppShortcutCreator(app_data_dir, shortcut_info) {}
 
   MOCK_CONST_METHOD0(GetAppBundlesByIdUnsorted, std::vector<base::FilePath>());
-  MOCK_CONST_METHOD0(RevealAppShimInFinder, void());
+  MOCK_CONST_METHOD1(RevealAppShimInFinder, void(const base::FilePath&));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(WebAppShortcutCreatorMock);
@@ -551,11 +551,11 @@
 TEST_F(WebAppShortcutCreatorTest, RevealAppShimInFinder) {
   WebAppShortcutCreatorMock shortcut_creator(app_data_dir_, info_.get());
 
-  EXPECT_CALL(shortcut_creator, RevealAppShimInFinder()).Times(0);
+  EXPECT_CALL(shortcut_creator, RevealAppShimInFinder(_)).Times(0);
   EXPECT_TRUE(shortcut_creator.CreateShortcuts(SHORTCUT_CREATION_AUTOMATED,
                                                ShortcutLocations()));
 
-  EXPECT_CALL(shortcut_creator, RevealAppShimInFinder());
+  EXPECT_CALL(shortcut_creator, RevealAppShimInFinder(_));
   EXPECT_TRUE(shortcut_creator.CreateShortcuts(SHORTCUT_CREATION_BY_USER,
                                                ShortcutLocations()));
 }
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc
index c4b5505..eda05ebe 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.cc
@@ -13,7 +13,6 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/optional.h"
-#include "build/build_config.h"
 #include "chrome/browser/extensions/crx_installer.h"
 #include "chrome/browser/extensions/launch_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -37,10 +36,6 @@
 #include "extensions/common/extension_set.h"
 #include "url/gurl.h"
 
-#if defined(OS_MACOSX)
-#include "chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.h"
-#endif
-
 namespace extensions {
 
 static constexpr char kInstallResultExtensionErrorHistogramName[] =
@@ -234,26 +229,6 @@
       FROM_HERE, base::BindOnce(std::move(callback), uninstalled));
 }
 
-bool BookmarkAppInstallFinalizer::CanRevealAppShim() const {
-#if defined(OS_MACOSX)
-  return true;
-#else   // defined(OS_MACOSX)
-  return false;
-#endif  // !defined(OS_MACOSX)
-}
-
-void BookmarkAppInstallFinalizer::RevealAppShim(const web_app::AppId& app_id) {
-  DCHECK(CanRevealAppShim());
-#if defined(OS_MACOSX)
-  const Extension* app = GetEnabledExtension(app_id);
-  DCHECK(app);
-  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
-          ::switches::kDisableHostedAppShimCreation)) {
-    web_app::RevealAppShimInFinderForApp(profile_, app);
-  }
-#endif  // defined(OS_MACOSX)
-}
-
 void BookmarkAppInstallFinalizer::SetCrxInstallerFactoryForTesting(
     CrxInstallerFactory crx_installer_factory) {
   crx_installer_factory_ = crx_installer_factory;
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h
index 6e0d194..7f40a251b 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h
+++ b/chrome/browser/web_applications/extensions/bookmark_app_install_finalizer.h
@@ -54,8 +54,6 @@
                                   UninstallWebAppCallback callback) override;
   bool WasExternalAppUninstalledByUser(
       const web_app::AppId& app_id) const override;
-  bool CanRevealAppShim() const override;
-  void RevealAppShim(const web_app::AppId& app_id) override;
 
   using CrxInstallerFactory =
       base::RepeatingCallback<scoped_refptr<CrxInstaller>(Profile*)>;
diff --git a/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc b/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc
index b2d26069..325b2654 100644
--- a/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc
+++ b/chrome/browser/web_applications/extensions/install_manager_bookmark_app_unittest.cc
@@ -108,7 +108,6 @@
   void ReparentTab(const web_app::AppId& app_id,
                    bool shortcut_created,
                    content::WebContents* web_contents) override {}
-  void RevealAppShim(const web_app::AppId& app_id) override {}
 };
 
 }  // namespace
diff --git a/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc b/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc
index 517c2d9..23c4f91 100644
--- a/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc
@@ -137,7 +137,6 @@
     return num_add_app_to_quick_launch_bar_calls_;
   }
   size_t num_reparent_tab_calls() { return num_reparent_tab_calls_; }
-  size_t num_reveal_appshim_calls() { return num_reveal_appshim_calls_; }
 
   // InstallFinalizer
   void FinalizeInstall(const WebApplicationInfo& web_app_info,
@@ -257,12 +256,6 @@
     ++num_reparent_tab_calls_;
   }
 
-  bool CanRevealAppShim() const override { return true; }
-
-  void RevealAppShim(const AppId& app_id) override {
-    ++num_reveal_appshim_calls_;
-  }
-
  private:
   TestAppRegistrar* registrar_ = nullptr;
 
@@ -272,7 +265,6 @@
 
   size_t num_add_app_to_quick_launch_bar_calls_ = 0;
   size_t num_reparent_tab_calls_ = 0;
-  size_t num_reveal_appshim_calls_ = 0;
 
   std::map<GURL, std::pair<AppId, InstallResultCode>>
       next_finalize_install_results_;
@@ -422,7 +414,6 @@
 
         EXPECT_EQ(1u, finalizer()->num_add_app_to_quick_launch_bar_calls());
         EXPECT_EQ(0u, finalizer()->num_reparent_tab_calls());
-        EXPECT_EQ(0u, finalizer()->num_reveal_appshim_calls());
 
         EXPECT_FALSE(web_app_info().open_as_window);
         EXPECT_EQ(WebappInstallSource::INTERNAL_DEFAULT,
@@ -482,7 +473,6 @@
 
         EXPECT_EQ(1u, finalizer()->num_add_app_to_quick_launch_bar_calls());
         EXPECT_EQ(0u, finalizer()->num_reparent_tab_calls());
-        EXPECT_EQ(0u, finalizer()->num_reveal_appshim_calls());
 
         run_loop.Quit();
       }));
@@ -510,7 +500,6 @@
 
         EXPECT_EQ(0u, finalizer()->num_add_app_to_quick_launch_bar_calls());
         EXPECT_EQ(0u, finalizer()->num_reparent_tab_calls());
-        EXPECT_EQ(0u, finalizer()->num_reveal_appshim_calls());
 
         run_loop.Quit();
       }));
@@ -540,7 +529,6 @@
 
         EXPECT_EQ(0u, finalizer()->num_add_app_to_quick_launch_bar_calls());
         EXPECT_EQ(0u, finalizer()->num_reparent_tab_calls());
-        EXPECT_EQ(0u, finalizer()->num_reveal_appshim_calls());
 
         run_loop.Quit();
       }));
diff --git a/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.h b/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.h
index 5902181..c50a485a 100644
--- a/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.h
+++ b/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.h
@@ -11,27 +11,15 @@
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
 
-class Profile;
-
 namespace base {
 class CommandLine;
 }
 
-namespace extensions {
-class Extension;
-}
-
 namespace web_app {
 
 // Rebuild the shortcut and relaunch it.
 bool MaybeRebuildShortcut(const base::CommandLine& command_line);
 
-// Reveals app shim in Finder given a profile and app.
-// Calls RevealAppShimInFinderForAppOnFileThread and schedules it
-// on the FILE thread.
-void RevealAppShimInFinderForApp(Profile* profile,
-                                 const extensions::Extension* app);
-
 }  // namespace web_app
 
 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_WEB_APP_EXTENSION_SHORTCUT_MAC_H_
diff --git a/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm b/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
index c28c2c3..aeab875 100644
--- a/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
+++ b/chrome/browser/web_applications/extensions/web_app_extension_shortcut_mac.mm
@@ -68,20 +68,6 @@
 
 namespace web_app {
 
-void RevealAppShimInFinderForAppOnFileThread(
-    const base::FilePath& app_path,
-    const ShortcutInfo& shortcut_info) {
-  WebAppShortcutCreator shortcut_creator(app_path, &shortcut_info);
-  shortcut_creator.RevealAppShimInFinder();
-}
-
-void RevealAppShimInFinderForApp(Profile* profile,
-                                 const extensions::Extension* app) {
-  web_app::internals::PostShortcutIOTask(
-      base::BindOnce(&RevealAppShimInFinderForAppOnFileThread, app->path()),
-      ShortcutInfoForExtensionAndProfile(app, profile));
-}
-
 void RebuildAppAndLaunch(std::unique_ptr<ShortcutInfo> shortcut_info) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
diff --git a/chrome/browser/web_applications/test/test_install_finalizer.cc b/chrome/browser/web_applications/test/test_install_finalizer.cc
index e423df7..3bd4f8d 100644
--- a/chrome/browser/web_applications/test/test_install_finalizer.cc
+++ b/chrome/browser/web_applications/test/test_install_finalizer.cc
@@ -126,14 +126,6 @@
   ++num_reparent_tab_calls_;
 }
 
-bool TestInstallFinalizer::CanRevealAppShim() const {
-  return true;
-}
-
-void TestInstallFinalizer::RevealAppShim(const AppId& app_id) {
-  ++num_reveal_appshim_calls_;
-}
-
 void TestInstallFinalizer::SetNextFinalizeInstallResult(
     const AppId& app_id,
     InstallResultCode code) {
diff --git a/chrome/browser/web_applications/test/test_install_finalizer.h b/chrome/browser/web_applications/test/test_install_finalizer.h
index 9dbd0597..d7c7d53 100644
--- a/chrome/browser/web_applications/test/test_install_finalizer.h
+++ b/chrome/browser/web_applications/test/test_install_finalizer.h
@@ -57,8 +57,6 @@
   void ReparentTab(const AppId& app_id,
                    bool shortcut_created,
                    content::WebContents* web_contents) override;
-  bool CanRevealAppShim() const override;
-  void RevealAppShim(const AppId& app_id) override;
 
   void SetNextFinalizeInstallResult(const AppId& app_id,
                                     InstallResultCode code);
@@ -83,7 +81,6 @@
   }
 
   int num_reparent_tab_calls() { return num_reparent_tab_calls_; }
-  int num_reveal_appshim_calls() { return num_reveal_appshim_calls_; }
   int num_add_app_to_quick_launch_bar_calls() {
     return num_add_app_to_quick_launch_bar_calls_;
   }
@@ -103,7 +100,6 @@
   std::set<AppId> user_uninstalled_external_apps_;
 
   int num_reparent_tab_calls_ = 0;
-  int num_reveal_appshim_calls_ = 0;
   int num_add_app_to_quick_launch_bar_calls_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(TestInstallFinalizer);
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 81717881..bb64c14 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -446,17 +446,6 @@
   std::move(callback).Run(installed_app_id, code);
 }
 
-bool WebAppInstallFinalizer::CanRevealAppShim() const {
-  // TODO(loyso): Implement it.
-  NOTIMPLEMENTED();
-  return false;
-}
-
-void WebAppInstallFinalizer::RevealAppShim(const AppId& app_id) {
-  // TODO(loyso): Implement it.
-  NOTIMPLEMENTED();
-}
-
 WebAppRegistrar& WebAppInstallFinalizer::GetWebAppRegistrar() const {
   WebAppRegistrar* web_app_registrar = registrar().AsWebAppRegistrar();
   DCHECK(web_app_registrar);
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h
index 3434cbc..978465f 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.h
+++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -50,8 +50,6 @@
   void UninstallExternalAppByUser(const AppId& app_id,
                                   UninstallWebAppCallback callback) override;
   bool WasExternalAppUninstalledByUser(const AppId& app_id) const override;
-  bool CanRevealAppShim() const override;
-  void RevealAppShim(const AppId& app_id) override;
 
  private:
   void UninstallWebApp(const AppId& app_id, UninstallWebAppCallback callback);
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc
index 303073f..e18cb5e 100644
--- a/chrome/browser/web_applications/web_app_install_task.cc
+++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -845,10 +845,6 @@
 
     if (can_reparent_tab && web_app_info->open_as_window)
       install_finalizer_->ReparentTab(app_id, shortcut_created, web_contents());
-
-    // TODO(loyso): Make revealing app shim independent from CanReparentTab.
-    if (can_reparent_tab && install_finalizer_->CanRevealAppShim())
-      install_finalizer_->RevealAppShim(app_id);
   }
 
   // Enable file handlers, if the app is locally installed.
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc
index 006fb22..9bcbb425 100644
--- a/chrome/browser/web_applications/web_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_task_unittest.cc
@@ -787,7 +787,6 @@
 
   EXPECT_EQ(1u, test_shortcut_manager().num_create_shortcuts_calls());
   EXPECT_EQ(1, test_install_finalizer().num_reparent_tab_calls());
-  EXPECT_EQ(1, test_install_finalizer().num_reveal_appshim_calls());
 
 #if defined(OS_CHROMEOS)
   const int expected_num_add_app_to_quick_launch_bar_calls = 0;
@@ -811,7 +810,6 @@
 
   EXPECT_EQ(0u, test_shortcut_manager().num_create_shortcuts_calls());
   EXPECT_EQ(0, test_install_finalizer().num_reparent_tab_calls());
-  EXPECT_EQ(0, test_install_finalizer().num_reveal_appshim_calls());
   EXPECT_EQ(0,
             test_install_finalizer().num_add_app_to_quick_launch_bar_calls());
 }
diff --git a/chrome/browser/xsurface/BUILD.gn b/chrome/browser/xsurface/BUILD.gn
index ee438487..7315eba 100644
--- a/chrome/browser/xsurface/BUILD.gn
+++ b/chrome/browser/xsurface/BUILD.gn
@@ -14,5 +14,5 @@
     "android/java/src/org/chromium/chrome/browser/xsurface/SurfaceDependencyProvider.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/SurfaceRenderer.java",
   ]
-  deps = []
+  deps = [ "//third_party/android_deps:androidx_annotation_annotation_java" ]
 }
diff --git a/chrome/browser/xsurface/README.md b/chrome/browser/xsurface/README.md
index c9580e3..2d09ddbb 100644
--- a/chrome/browser/xsurface/README.md
+++ b/chrome/browser/xsurface/README.md
@@ -6,6 +6,6 @@
 data driven.
 
 Note that this location defines mostly just the interfaces for this feature. The
-bulk of the actual implemnetation is provided by downstream. This means that
+bulk of the actual implementation is provided by downstream. This means that
 changes to these interfaces will likely cause downstream build failures. Please
 do not TBR changes through without engaging OWNERS.
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/FeedActionsHandler.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/FeedActionsHandler.java
index 930540f..5ba14996 100644
--- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/FeedActionsHandler.java
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/FeedActionsHandler.java
@@ -14,26 +14,28 @@
      * Requests additional content to be loaded. Once the load is completed, onStreamUpdated will be
      * called.
      */
-    void loadMore();
+    default void loadMore() {}
 
     /**
      * Sends data back to the server when content is clicked.
      */
-    void processThereAndBackAgainData(byte[] data);
+    default void processThereAndBackAgainData(byte[] data) {}
 
     /**
      * Requests to dismiss a card. A change ID will be returned and it can be used to commit or
      * discard the change.
      */
-    int requestDismissal();
+    default int requestDismissal() {
+        return 0;
+    }
 
     /**
      * Commits a previous requested dismissal denoted by change ID.
      */
-    void commitDismissal(int changeId);
+    default void commitDismissal(int changeId) {}
 
     /**
      * Discards a previous requested dismissal denoted by change ID.
      */
-    void discardDismissal(int changeId);
+    default void discardDismissal(int changeId) {}
 }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/HybridListRenderer.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/HybridListRenderer.java
index f004afa..125e231de 100644
--- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/HybridListRenderer.java
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/HybridListRenderer.java
@@ -6,6 +6,8 @@
 
 import android.view.View;
 
+import androidx.annotation.Nullable;
+
 /**
  * A renderer that can handle mixing externally-provided views with native Android views
  * in a RecyclerView.
@@ -16,17 +18,20 @@
      * @return a View that the HybridListRenderer is managing, which can then be
      * attached to other view
      */
-    View bind(ListContentManager manager);
+    @Nullable
+    default View bind(ListContentManager manager) {
+        return null;
+    }
 
     /**
      * Unbinds a previously attached recyclerview and contentmanager.
      *
      * Does nothing if nothing was previously bound.
      */
-    void unbind();
+    default void unbind() {}
 
     /**
      * Updates the renderer with templates and initializing data.
      */
-    void update(byte[] data);
+    default void update(byte[] data) {}
 }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManager.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManager.java
index ebf8cee..c64ab60 100644
--- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManager.java
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ListContentManager.java
@@ -7,6 +7,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.annotation.Nullable;
+
 import java.util.Map;
 
 /**
@@ -17,13 +19,20 @@
  */
 public interface ListContentManager {
     /** Returns whether the item at index is a native view or not. */
-    boolean isNativeView(int index);
+    default boolean isNativeView(int index) {
+        return false;
+    }
 
     /** Gets the bytes needed to render an external view. */
-    byte[] getExternalViewBytes(int index);
+    default byte[] getExternalViewBytes(int index) {
+        return new byte[0];
+    }
 
     /** Returns map of values which should go in the context of an external view. */
-    Map<String, Object> getContextValues(int index);
+    @Nullable
+    default Map<String, Object> getContextValues(int index) {
+        return null;
+    }
 
     /**
      * Returns the inflated native view.
@@ -31,19 +40,23 @@
      * View should not be attached to parent. {@link bindNativeView} will
      * be called later to attach more information to the view.
      */
-    View getNativeView(int index, ViewGroup parent);
+    default View getNativeView(int index, ViewGroup parent) {
+        return null;
+    }
 
     /**
      * Binds the data at the specified location.
      */
-    void bindNativeView(int index, View v);
+    default void bindNativeView(int index, View v) {}
 
     /** Returns number of items to show. */
-    int getItemCount();
+    default int getItemCount() {
+        return 0;
+    }
 
     /** Adds an observer to be notified when the list content changes. */
-    void addObserver(ListContentManagerObserver o);
+    default void addObserver(ListContentManagerObserver o) {}
 
     /** Removes the observer so it's no longer notified of content changes. */
-    void removeObserver(ListContentManagerObserver o);
+    default void removeObserver(ListContentManagerObserver o) {}
 }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java
index c8e116f8..da906ba 100644
--- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java
@@ -13,10 +13,10 @@
     /**
      * Navigates the current tab to a particular URL.
      */
-    void navigateTab(String url);
+    default void navigateTab(String url) {}
 
     /**
      * Navigates a new tab to a particular URL.
      */
-    void navigateNewTab(String url);
+    default void navigateNewTab(String url) {}
 }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceDependencyProvider.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceDependencyProvider.java
index 8d9abf6..32186cb 100644
--- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceDependencyProvider.java
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceDependencyProvider.java
@@ -6,16 +6,21 @@
 
 import android.content.Context;
 
+import androidx.annotation.Nullable;
+
 /**
  * Provides logging and context for an external surface.
  */
 public interface SurfaceDependencyProvider {
     /** @return the context associated with the application. */
-    Context getContext();
+    @Nullable
+    default Context getContext() {
+        return null;
+    }
 
     /** @see {Log.e} */
-    void logError(String tag, String messageTemplate, Object... args);
+    default void logError(String tag, String messageTemplate, Object... args) {}
 
     /** @see {Log.w} */
-    void logWarning(String tag, String messageTemplate, Object... args);
+    default void logWarning(String tag, String messageTemplate, Object... args) {}
 }
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceRenderer.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceRenderer.java
index af50982..de56baf1 100644
--- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceRenderer.java
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceRenderer.java
@@ -6,6 +6,8 @@
 
 import android.view.View;
 
+import androidx.annotation.Nullable;
+
 import java.util.Map;
 
 /**
@@ -13,7 +15,7 @@
  */
 public interface SurfaceRenderer {
     /** Update the card renderer with shared data bytes. */
-    void update(byte[] data);
+    default void update(byte[] data) {}
 
     /**
      * Turns a stream of externally-provided bytes into an Android View.
@@ -21,5 +23,8 @@
      * @param renderData externally-provided bytes to be rendered.
      * @param contextValues additional context to be incorporated into the view.
      */
-    View render(byte[] renderData, Map<String, Object> contextValues);
+    @Nullable
+    default View render(byte[] renderData, Map<String, Object> contextValues) {
+        return null;
+    }
 }
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 8fb01356..294e8c49 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -671,6 +671,8 @@
 
   if (enable_extensions) {
     sources += [
+      "extensions/api/extension_action/action_info_test_util.cc",
+      "extensions/api/extension_action/action_info_test_util.h",
       "extensions/extension_test_util.cc",
       "extensions/extension_test_util.h",
     ]
diff --git a/chrome/common/extensions/api/extension_action/action_info_test_util.cc b/chrome/common/extensions/api/extension_action/action_info_test_util.cc
new file mode 100644
index 0000000..0ea3ce5
--- /dev/null
+++ b/chrome/common/extensions/api/extension_action/action_info_test_util.cc
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/extensions/api/extension_action/action_info_test_util.h"
+
+#include "extensions/common/manifest_constants.h"
+
+namespace extensions {
+
+const char* GetManifestKeyForActionType(ActionInfo::Type type) {
+  const char* action_key = nullptr;
+  switch (type) {
+    case ActionInfo::TYPE_BROWSER:
+      action_key = manifest_keys::kBrowserAction;
+      break;
+    case ActionInfo::TYPE_PAGE:
+      action_key = manifest_keys::kPageAction;
+      break;
+    case ActionInfo::TYPE_ACTION:
+      action_key = manifest_keys::kAction;
+      break;
+  }
+
+  return action_key;
+}
+
+const ActionInfo* GetActionInfoOfType(const Extension& extension,
+                                      ActionInfo::Type type) {
+  const ActionInfo* action_info = ActionInfo::GetAnyActionInfo(&extension);
+  return (action_info && action_info->type == type) ? action_info : nullptr;
+}
+
+}  // namespace extensions
diff --git a/chrome/common/extensions/api/extension_action/action_info_test_util.h b/chrome/common/extensions/api/extension_action/action_info_test_util.h
new file mode 100644
index 0000000..04dd248
--- /dev/null
+++ b/chrome/common/extensions/api/extension_action/action_info_test_util.h
@@ -0,0 +1,25 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_EXTENSIONS_API_EXTENSION_ACTION_ACTION_INFO_TEST_UTIL_H_
+#define CHROME_COMMON_EXTENSIONS_API_EXTENSION_ACTION_ACTION_INFO_TEST_UTIL_H_
+
+#include "chrome/common/extensions/api/extension_action/action_info.h"
+
+namespace extensions {
+class Extension;
+
+// Retrieves the manifest key for the given action |type|.
+const char* GetManifestKeyForActionType(ActionInfo::Type type);
+
+// Retrieves the ActionInfo for the |extension| if and only if it
+// corresponds to the specified |type|. This is useful for testing to ensure
+// the type is specified correctly, since most production code is type-
+// agnostic.
+const ActionInfo* GetActionInfoOfType(const Extension& extension,
+                                      ActionInfo::Type type);
+
+}  // namespace extensions
+
+#endif  // CHROME_COMMON_EXTENSIONS_API_EXTENSION_ACTION_ACTION_INFO_TEST_UTIL_H_
diff --git a/chrome/common/extensions/manifest_handlers/extension_action_handler_unittest.cc b/chrome/common/extensions/manifest_handlers/extension_action_handler_unittest.cc
index 4c77ad2..d19e2fd 100644
--- a/chrome/common/extensions/manifest_handlers/extension_action_handler_unittest.cc
+++ b/chrome/common/extensions/manifest_handlers/extension_action_handler_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/values.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/api/extension_action/action_info.h"
+#include "chrome/common/extensions/api/extension_action/action_info_test_util.h"
 #include "components/version_info/channel.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
@@ -91,18 +92,7 @@
              "%s": %s
            })";
 
-    const char* action_key = nullptr;
-    switch (GetParam()) {
-      case ActionInfo::TYPE_BROWSER:
-        action_key = manifest_keys::kBrowserAction;
-        break;
-      case ActionInfo::TYPE_PAGE:
-        action_key = manifest_keys::kPageAction;
-        break;
-      case ActionInfo::TYPE_ACTION:
-        action_key = manifest_keys::kAction;
-        break;
-    }
+    const char* action_key = GetManifestKeyForActionType(GetParam());
 
     base::Value manifest_value = base::test::ParseJson(
         base::StringPrintf(kManifestStub, action_key, action_spec));
@@ -111,25 +101,6 @@
     return ManifestData(std::move(manifest_value), "test");
   }
 
-  // Returns the ActionInfo for the given |extension| corresponding with the
-  // action key of the test param.
-  const ActionInfo* GetActionInfo(const Extension& extension) {
-    const ActionInfo* action_info = nullptr;
-    switch (GetParam()) {
-      case ActionInfo::TYPE_BROWSER:
-        action_info = ActionInfo::GetBrowserActionInfo(&extension);
-        break;
-      case ActionInfo::TYPE_PAGE:
-        action_info = ActionInfo::GetPageActionInfo(&extension);
-        break;
-      case ActionInfo::TYPE_ACTION:
-        action_info = ActionInfo::GetExtensionActionInfo(&extension);
-        break;
-    }
-
-    return action_info;
-  }
-
  private:
   // The "action" key is restricted to trunk.
   ScopedCurrentChannel scoped_channel_{version_info::Channel::UNKNOWN};
@@ -149,7 +120,7 @@
   scoped_refptr<const Extension> extension =
       LoadAndExpectSuccess(GetManifestData(kValidAllFields));
   ASSERT_TRUE(extension);
-  const ActionInfo* action_info = GetActionInfo(*extension);
+  const ActionInfo* action_info = GetActionInfoOfType(*extension, GetParam());
   ASSERT_TRUE(action_info);
 
   EXPECT_EQ(extension->GetResourceURL("popup.html"),
@@ -169,7 +140,7 @@
   scoped_refptr<const Extension> extension =
       LoadAndExpectSuccess(GetManifestData(kValidNoFields));
   ASSERT_TRUE(extension);
-  const ActionInfo* action_info = GetActionInfo(*extension);
+  const ActionInfo* action_info = GetActionInfoOfType(*extension, GetParam());
   ASSERT_TRUE(action_info);
 
   EXPECT_EQ(GURL(), action_info->default_popup_url);
@@ -193,7 +164,7 @@
   scoped_refptr<const Extension> extension =
       LoadAndExpectSuccess(GetManifestData(kValidIconDictionary));
   ASSERT_TRUE(extension);
-  const ActionInfo* action_info = GetActionInfo(*extension);
+  const ActionInfo* action_info = GetActionInfoOfType(*extension, GetParam());
   ASSERT_TRUE(action_info);
 
   EXPECT_EQ(GURL(), action_info->default_popup_url);
@@ -283,7 +254,8 @@
       scoped_refptr<const Extension> extension =
           LoadAndExpectSuccess(GetManifestData(test_case.spec));
       ASSERT_TRUE(extension);
-      const ActionInfo* action_info = GetActionInfo(*extension);
+      const ActionInfo* action_info =
+          GetActionInfoOfType(*extension, GetParam());
       ASSERT_TRUE(action_info);
       EXPECT_EQ(*test_case.expected_state, action_info->default_state);
     } else {
diff --git a/chrome/renderer/resources/extensions/browser_action_custom_bindings.js b/chrome/renderer/resources/extensions/browser_action_custom_bindings.js
index 8e16e2c..1b1132a 100644
--- a/chrome/renderer/resources/extensions/browser_action_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/browser_action_custom_bindings.js
@@ -14,6 +14,9 @@
     setIcon(details, function(args) {
       bindingUtil.sendRequest(
           'browserAction.setIcon', [args, callback], undefined);
+    }.bind(this), function (errorMessage) {
+      // Propagate the error message.
+      bindingUtil.runCallbackWithLastError(errorMessage, callback);
     }.bind(this));
   });
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 312a8c8..f01bf92 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2388,6 +2388,7 @@
         "../browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc",
         "../browser/ui/ash/launcher/app_service/app_service_app_window_browsertest.cc",
         "../browser/ui/ash/launcher/app_service/app_service_shelf_context_menu_browsertest.cc",
+        "../browser/ui/ash/launcher/app_shortcut_launcher_item_controller_browsertest.cc",
         "../browser/ui/ash/launcher/arc_app_launcher_browsertest.cc",
         "../browser/ui/ash/launcher/browser_shortcut_launcher_item_controller_browsertest.cc",
         "../browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc",
diff --git a/chrome/test/data/android/render_tests/NewTabPageTest.focus_fake_box.Nexus_5X-23.png.sha1 b/chrome/test/data/android/render_tests/NewTabPageTest.focus_fake_box.Nexus_5X-23.png.sha1
new file mode 100644
index 0000000..6389072c
--- /dev/null
+++ b/chrome/test/data/android/render_tests/NewTabPageTest.focus_fake_box.Nexus_5X-23.png.sha1
@@ -0,0 +1 @@
+978cf88f5f04f0182dec99909ac1ee924b6459f3
\ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/browser_action/update_svg/background.js b/chrome/test/data/extensions/api_test/browser_action/update_svg/background.js
new file mode 100644
index 0000000..c9718cb
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/browser_action/update_svg/background.js
@@ -0,0 +1,39 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var inServiceWorker = 'ServiceWorkerGlobalScope' in self;
+
+function updateBrowserAction() {
+  chrome.browserAction.setTitle({title: 'Modified'}, function() {
+    chrome.browserAction.setIcon({path: 'icon2.svg'}, function() {
+      if (inServiceWorker) {
+        chrome.test.notifyFail(chrome.runtime.lastError.message);
+      } else {
+        chrome.test.assertNoLastError();
+        chrome.browserAction.setBadgeText({text: 'badge'}, function() {
+          chrome.browserAction.setBadgeBackgroundColor(
+              {color: [255,255,255,255]}, function() {
+            chrome.test.notifyPass();
+          });
+        });
+      }
+    });
+  });
+}
+
+chrome.extension.isAllowedIncognitoAccess(function(isAllowedAccess) {
+  if (isAllowedAccess == true) {
+    chrome.test.sendMessage('incognito ready', function(message) {
+      if (message == 'incognito update') {
+        updateBrowserAction();
+      }
+    });
+  }
+});
+
+chrome.test.sendMessage('ready', function(message) {
+  if (message == 'update') {
+    updateBrowserAction();
+  }
+});
diff --git a/chrome/test/data/extensions/api_test/browser_action/update_svg/icon.svg b/chrome/test/data/extensions/api_test/browser_action/update_svg/icon.svg
new file mode 100644
index 0000000..672f292
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/browser_action/update_svg/icon.svg
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   id="svg8"
+   version="1.1"
+   viewBox="0 0 5.644444 5.644444"
+   height="5.644444mm"
+   width="5.644444mm">
+  <defs
+     id="defs2" />
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     transform="translate(-228.49921,-236.7254)"
+     id="layer1">
+    <image
+       width="5.644444"
+       height="5.644444"
+       preserveAspectRatio="none"
+       xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHBy
+b2ZpbGUAADjLnVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8ig
+iAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIe
+EeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCE
+AcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCR
+ACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDI
+IyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKB
+NA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt
+/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48
+/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUi
+iUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8/
+/UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSA
+HHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgj
+jggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3U
+DLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNj
+y7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKT
+qEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBoj
+k8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2o
+oVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0
+dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyov
+VKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNM
+w09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H
+45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5B
+x0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U
+/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk
+423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2
+uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuu
+tm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP
+2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/u
+Nu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+
+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+O
+PzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeG
+P45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5
+LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWO
+CnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9
+MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/
+zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2
+Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cV
+f9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7
+g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbV
+ZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1V
+jZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sf
+D5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4
+dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3d
+vfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP
+/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/
+bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz
+/FpeimgAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAAlwSFlz
+AAALEwAACxMBAJqcGAAAABpJREFUOMtj/M/A8J+BAsA4asCoAaMGDBcDAKXUH/FigCTdAAAAAElF
+TkSuQmCC
+"
+       id="image72"
+       x="228.49921"
+       y="236.7254" />
+  </g>
+</svg>
diff --git a/chrome/test/data/extensions/api_test/browser_action/update_svg/icon2.svg b/chrome/test/data/extensions/api_test/browser_action/update_svg/icon2.svg
new file mode 100644
index 0000000..a3f795e
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/browser_action/update_svg/icon2.svg
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="5.644444mm"
+   height="5.644444mm"
+   viewBox="0 0 5.644444 5.644444"
+   version="1.1"
+   id="svg230"
+   inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+   sodipodi:docname="icon2.svg">
+  <defs
+     id="defs224" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.35"
+     inkscape:cx="-83.619"
+     inkscape:cy="173.52377"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="2560"
+     inkscape:window-height="1375"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata227">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-127.95753,-189.10039)">
+    <image
+       y="189.10039"
+       x="127.95753"
+       id="image294"
+       xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHBy
+b2ZpbGUAADjLnVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8ig
+iAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIe
+EeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCE
+AcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCR
+ACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDI
+IyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKB
+NA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt
+/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48
+/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUi
+iUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8/
+/UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSA
+HHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgj
+jggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3U
+DLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNj
+y7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKT
+qEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBoj
+k8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2o
+oVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0
+dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyov
+VKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNM
+w09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H
+45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5B
+x0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U
+/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk
+423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2
+uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuu
+tm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP
+2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/u
+Nu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+
+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+O
+PzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeG
+P45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5
+LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWO
+CnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9
+MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/
+zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2
+Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cV
+f9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7
+g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbV
+ZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1V
+jZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sf
+D5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4
+dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3d
+vfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP
+/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/
+bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz
+/FpeimgAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAAlwSFlz
+AAALEwAACxMBAJqcGAAAABpJREFUOMtj/M/A8J+BAsA4asCoAaMGDBcDAKXUH/FigCTdAAAAAElF
+TkSuQmCC
+"
+       preserveAspectRatio="none"
+       height="5.644444"
+       width="5.644444" />
+  </g>
+</svg>
diff --git a/chrome/test/data/extensions/api_test/browser_action/update_svg/manifest.json b/chrome/test/data/extensions/api_test/browser_action/update_svg/manifest.json
new file mode 100644
index 0000000..716be5a
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/browser_action/update_svg/manifest.json
@@ -0,0 +1,13 @@
+{
+  "name": "A browser action test to verify updates to the icon and title.",
+  "version": "1.0",
+  "manifest_version": 2,
+  "background": {
+    "persistent": false,
+    "scripts": ["background.js"]
+  },
+  "browser_action": {
+    "default_title": "This is the default title.",
+    "default_icon": "icon.svg"
+  }
+}
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 120c486f..69bd3e3 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -101,6 +101,7 @@
     "settings/a11y/basic_a11y_test.js",
     "settings/a11y/edit_dictionary_a11y_test.js",
     "settings/a11y/passwords_a11y_test.js",
+    "settings/a11y/v3_a11y_browsertest.js",
     "settings/cr_settings_browsertest.js",
     "settings/cr_settings_v3_browsertest.js",
     "settings/help_page_browsertest.js",
@@ -115,6 +116,7 @@
     "a11y/accessibility_test.js",
     "polymer_browser_test_base.js",
     "settings/a11y/settings_accessibility_test.js",
+    "settings/a11y/settings_accessibility_v3_test.js",
     "//third_party/axe-core/axe.js",
   ]
 
diff --git a/chrome/test/data/webui/chromeos/print_management/print_management_test.js b/chrome/test/data/webui/chromeos/print_management/print_management_test.js
index 1d1b6b0b..386d6006 100644
--- a/chrome/test/data/webui/chromeos/print_management/print_management_test.js
+++ b/chrome/test/data/webui/chromeos/print_management/print_management_test.js
@@ -7,7 +7,7 @@
 import 'chrome://print-management/print_management.js';
 
 import {setMetadataProviderForTesting} from 'chrome://print-management/mojo_interface_provider.js';
-import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {flushTasks} from 'chrome://test/test_util.m.js';
 
 const CompletionStatus = {
   FAILED: 0,
@@ -84,7 +84,6 @@
  * @return {!Array<!HTMLElement>}
  */
 function getPrintJobEntries(page) {
-  flush();
   const entryList = page.$$('#entryList');
   return Array.from(
       entryList.querySelectorAll('print-job-entry:not([hidden])'));
@@ -198,7 +197,7 @@
     mojoApi_.setPrintJobs(printJobs);
     page = document.createElement('print-management');
     document.body.appendChild(page);
-    flush();
+    return flushTasks();
   }
 
   test('PrintHistoryListIsSortedReverseChronologically', () => {
@@ -217,11 +216,13 @@
     // Initialize with a reversed array of |expectedArr|, since we expect the
     // app to sort the list when it first loads. Since reverse() mutates the
     // original array, use a copy array to prevent mutating |expectedArr|.
-    initializePrintManagementApp(expectedArr.slice().reverse());
-
-    mojoApi_.whenCalled('getPrintJobs').then(() => {
-      verifyPrintJobs(expectedArr, getPrintJobEntries(page));
-    });
+    initializePrintManagementApp(expectedArr.slice().reverse())
+        .then(() => {
+          return mojoApi_.whenCalled('getPrintJobs');
+        })
+        .then(() => {
+          verifyPrintJobs(expectedArr, getPrintJobEntries(page));
+        });
   });
 });
 
diff --git a/chrome/test/data/webui/new_tab_page/customize_dialog_test.js b/chrome/test/data/webui/new_tab_page/customize_dialog_test.js
index ae378c5..84e518f 100644
--- a/chrome/test/data/webui/new_tab_page/customize_dialog_test.js
+++ b/chrome/test/data/webui/new_tab_page/customize_dialog_test.js
@@ -100,8 +100,10 @@
       assertHidden(bottom);
     }
 
-    test('menu', () => testScrollBorders(customizeDialog.$.menuContainer));
-    test('pages', () => testScrollBorders(customizeDialog.$.pagesContainer));
+    // Disabled for flakiness, see https://crbug.com/1066459.
+    test.skip('menu', () => testScrollBorders(customizeDialog.$.menuContainer));
+    test.skip(
+        'pages', () => testScrollBorders(customizeDialog.$.pagesContainer));
   });
 
   suite('backgrounds', () => {
diff --git a/chrome/test/data/webui/new_tab_page/logo_test.js b/chrome/test/data/webui/new_tab_page/logo_test.js
index 88e03726..1be5b4f8 100644
--- a/chrome/test/data/webui/new_tab_page/logo_test.js
+++ b/chrome/test/data/webui/new_tab_page/logo_test.js
@@ -5,7 +5,7 @@
 import 'chrome://new-tab-page/logo.js';
 
 import {BrowserProxy} from 'chrome://new-tab-page/browser_proxy.js';
-import {assertNotStyle, assertStyle, createTestProxy} from 'chrome://test/new_tab_page/test_support.js';
+import {assertNotStyle, assertStyle, createTestProxy, keydown} from 'chrome://test/new_tab_page/test_support.js';
 import {eventToPromise, flushTasks} from 'chrome://test/test_util.m.js';
 
 suite('NewTabPageLogoTest', () => {
@@ -218,6 +218,27 @@
     assertEquals(url, 'https://foo.com');
   });
 
+  [' ', 'Enter'].forEach(key => {
+    test(`pressing ${key} on simple doodle opens link`, async () => {
+      // Arrange.
+      const logo = await createLogo({
+        content: {
+          imageDoodle: {
+            imageUrl: {url: 'data:foo'},
+            onClickUrl: {url: 'https://foo.com'},
+          }
+        }
+      });
+
+      // Act.
+      keydown(logo.$.image, key);
+      const url = await testProxy.whenCalled('open');
+
+      // Assert.
+      assertEquals(url, 'https://foo.com');
+    });
+  });
+
   test('clicking image of animated doodle starts animation', async () => {
     // Arrange.
     const logo = await createLogo({
diff --git a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js
index dc03db6..84a2abc 100644
--- a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js
+++ b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js
@@ -59,8 +59,7 @@
   }
 };
 
-// Disabled for flakiness, see https://crbug.com/1066459
-TEST_F('NewTabPageCustomizeDialogTest', 'DISABLED_All', function() {
+TEST_F('NewTabPageCustomizeDialogTest', 'All', function() {
   mocha.run();
 });
 
diff --git a/chrome/test/data/webui/settings/a11y/about_a11y_v3_test.js b/chrome/test/data/webui/settings/a11y/about_a11y_v3_test.js
new file mode 100644
index 0000000..43b1a4c
--- /dev/null
+++ b/chrome/test/data/webui/settings/a11y/about_a11y_v3_test.js
@@ -0,0 +1,15 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {routes} from 'chrome://settings/settings.js';
+
+// Set the URL to be that of specific route to load upon injecting
+// settings-ui. Simply calling
+// settings.Router.getInstance().navigateTo(route) prevents use of mock APIs
+// for fake data.
+window.history.pushState('object or string', 'Test', routes.ABOUT.path);
+const settingsUi = document.createElement('settings-ui');
+document.body.appendChild(settingsUi);
+document.dispatchEvent(new CustomEvent('a11y-setup-complete'));
diff --git a/chrome/test/data/webui/settings/a11y/accessibility_a11y_v3_test.js b/chrome/test/data/webui/settings/a11y/accessibility_a11y_v3_test.js
new file mode 100644
index 0000000..9c89868
--- /dev/null
+++ b/chrome/test/data/webui/settings/a11y/accessibility_a11y_v3_test.js
@@ -0,0 +1,14 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://settings/lazy_load.js';
+
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {Router, routes} from 'chrome://settings/settings.js';
+
+const ui = document.createElement('settings-ui');
+document.body.appendChild(ui);
+Router.getInstance().navigateTo(routes.ACCESSIBILITY);
+flush();
+document.dispatchEvent(new CustomEvent('a11y-setup-complete'));
diff --git a/chrome/test/data/webui/settings/a11y/basic_a11y_v3_test.js b/chrome/test/data/webui/settings/a11y/basic_a11y_v3_test.js
new file mode 100644
index 0000000..4a755db
--- /dev/null
+++ b/chrome/test/data/webui/settings/a11y/basic_a11y_v3_test.js
@@ -0,0 +1,11 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://settings/settings.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+const ui = document.createElement('settings-ui');
+document.body.appendChild(ui);
+flush();
+document.dispatchEvent(new CustomEvent('a11y-setup-complete'));
diff --git a/chrome/test/data/webui/settings/a11y/edit_dictionary_a11y_v3_test.js b/chrome/test/data/webui/settings/a11y/edit_dictionary_a11y_v3_test.js
new file mode 100644
index 0000000..a4fb5f0d
--- /dev/null
+++ b/chrome/test/data/webui/settings/a11y/edit_dictionary_a11y_v3_test.js
@@ -0,0 +1,36 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {LanguagesBrowserProxyImpl} from 'chrome://settings/lazy_load.js';
+import {Router, routes} from 'chrome://settings/settings.js';
+import {FakeLanguageSettingsPrivate} from 'chrome://test/settings/fake_language_settings_private.m.js';
+import {TestLanguagesBrowserProxy} from 'chrome://test/settings/test_languages_browser_proxy.m.js';
+import {flushTasks} from 'chrome://test/test_util.m.js';
+
+const fakeLanguageSettingsPrivate = new FakeLanguageSettingsPrivate();
+const fakeLanugagesProxy = new TestLanguagesBrowserProxy();
+fakeProxy.setLanguageSettingsPrivate(fakeLangugageSettingsPrivate);
+
+Router.getInstance().navigateTo(settings.routes.EDIT_DICTIONARY);
+const settingsUi = document.createElement('settings-ui');
+document.body.appendChild(settingsUi);
+
+const settingsMain = settingsUI.$.main;
+assertTrue(!!settingsMain);
+const settingsBasicPage = settingsMain.$$('settings-basic-page');
+assertTrue(!!settingsBasicPage);
+const languagesPage = settingsBasicPage.$$('settings-languages-page');
+assertTrue(!!languagesPage);
+const dictionaryPage = languagesPage.$$('settings-edit-dictionary-page');
+assertTrue(!!dictionaryPage);
+
+fakeLanguageSettingsPrivate.addSpellcheckWord('one');
+assertTrue(!!dictionaryPage.$$('#list'));
+assertEquals(1, dictionaryPage.$$('#list').items.length);
+
+flush();
+flushTasks().then(() => {
+  document.dispatchEvent(new CustomEvent('a11y-setup-complete'));
+});
diff --git a/chrome/test/data/webui/settings/a11y/passwords_a11y_v3_test.js b/chrome/test/data/webui/settings/a11y/passwords_a11y_v3_test.js
new file mode 100644
index 0000000..d747207
--- /dev/null
+++ b/chrome/test/data/webui/settings/a11y/passwords_a11y_v3_test.js
@@ -0,0 +1,58 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://settings/lazy_load.js';
+
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {PasswordManagerImpl, routes} from 'chrome://settings/settings.js';
+import {createPasswordEntry} from 'chrome://test/settings/passwords_and_autofill_fake_data.m.js';
+import {TestPasswordManagerProxy} from 'chrome://test/settings/test_password_manager_proxy.m.js';
+
+/** @type {PasswordsSectionElement}*/
+let passwordsSection = null;
+let passwordManager = null;
+let settingsUi = null;
+
+const whenReady = new Promise((resolve) => {
+  // Set the URL to be that of specific route to load upon injecting
+  // settings-ui. Simply calling
+  // settings.Router.getInstance().navigateTo(route) prevents use of mock
+  // APIs for fake data.
+  window.history.pushState('object or string', 'Test', routes.PASSWORDS.path);
+
+  PasswordManagerImpl.instance_ = new TestPasswordManagerProxy();
+  passwordManager = PasswordManagerImpl.getInstance();
+
+  settingsUi = document.createElement('settings-ui');
+
+  // The settings section will expand to load the PASSWORDS route (based on
+  // the URL set above) once the settings-ui element is attached
+  settingsUi.addEventListener('settings-section-expanded', () => {
+    // Passwords section should be loaded before setup is complete.
+    passwordsSection = settingsUi.$$('settings-main')
+                           .$$('settings-basic-page')
+                           .$$('settings-autofill-page')
+                           .$$('passwords-section');
+    assertTrue(!!passwordsSection);
+
+    assertEquals(passwordManager, passwordsSection.passwordManager_);
+
+    resolve();
+  });
+});
+
+document.body.appendChild(settingsUi);
+whenReady.then(() => {
+  const fakePasswords = [];
+  for (let i = 0; i < 10; i++) {
+    fakePasswords.push(createPasswordEntry());
+  }
+  // Set list of passwords.
+  passwordManager.lastCallback.addSavedPasswordListChangedListener(
+      fakePasswords);
+  flush();
+
+  assertEquals(10, passwordsSection.savedPasswords.length);
+  document.dispatchEvent(new CustomEvent('a11y-setup-complete'));
+});
diff --git a/chrome/test/data/webui/settings/a11y/settings_accessibility_v3_test.js b/chrome/test/data/webui/settings/a11y/settings_accessibility_v3_test.js
new file mode 100644
index 0000000..8dcf04d
--- /dev/null
+++ b/chrome/test/data/webui/settings/a11y/settings_accessibility_v3_test.js
@@ -0,0 +1,96 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** @fileoverview Runs the Polymer 3 Accessibility Settings tests. */
+
+// Polymer BrowserTest fixture and aXe-core accessibility audit.
+GEN_INCLUDE([
+  '//chrome/test/data/webui/a11y/accessibility_test.js',
+  '//chrome/test/data/webui/polymer_browser_test_base.js',
+]);
+
+GEN('#include "chrome/browser/ui/ui_features.h"');
+GEN('#include "services/network/public/cpp/features.h"');
+
+/**
+ * Test fixture for Accessibility of Chrome Settings.
+ * @constructor
+ * @extends {PolymerTest}
+ */
+function SettingsAccessibilityV3Test() {}
+
+// Default accessibility audit options. Specify in test definition to use.
+SettingsAccessibilityV3Test.axeOptions = {
+  'rules': {
+    // Disable 'skip-link' check since there are few tab stops before the main
+    // content.
+    'skip-link': {enabled: false},
+    // TODO(crbug.com/761461): enable after addressing flaky tests.
+    'color-contrast': {enabled: false},
+    // The HTML language attribute isn't set by the test_loader.html dummy file.
+    'html-has-lang': {enabled: false},
+  }
+};
+
+// Default accessibility audit options. Specify in test definition to use.
+SettingsAccessibilityV3Test.violationFilter = {
+  'aria-valid-attr': function(nodeResult) {
+    const attributeWhitelist = [
+      'aria-active-attribute',  // Polymer components use aria-active-attribute.
+      'aria-roledescription',   // This attribute is now widely supported.
+    ];
+
+    return attributeWhitelist.some(a => nodeResult.element.hasAttribute(a));
+  },
+  'aria-allowed-attr': function(nodeResult) {
+    const attributeWhitelist = [
+      'aria-roledescription',  // This attribute is now widely supported.
+    ];
+    return attributeWhitelist.some(a => nodeResult.element.hasAttribute(a));
+  },
+  'button-name': function(nodeResult) {
+    if (nodeResult.element.classList.contains('icon-expand-more')) {
+      return true;
+    }
+
+    // Ignore the <button> residing within cr-toggle and cr-checkbox, which has
+    // tabindex -1 anyway.
+    const parentNode = nodeResult.element.parentNode;
+    return parentNode && parentNode.host &&
+        (parentNode.host.tagName == 'CR-TOGGLE' ||
+         parentNode.host.tagName == 'CR-CHECKBOX');
+  },
+};
+
+SettingsAccessibilityV3Test.prototype = {
+  __proto__: PolymerTest.prototype,
+
+  /** @override */
+  browsePreload:
+      'chrome://settings/test_loader.html?module=settings/a11y/basic_a11y_v3_test.js',
+
+  // Include files that define the mocha tests.
+  extraLibraries: [
+    '//third_party/mocha/mocha.js',
+    '//chrome/test/data/webui/mocha_adapter.js',
+    '//third_party/axe-core/axe.js',
+  ],
+
+  /** @override */
+  featureList: {
+    enabled: [
+      'network::features::kOutOfBlinkCors',
+      'features::kSettingsPolymer3',
+    ],
+    disabled: [],
+  },
+
+  setUp: function() {
+    PolymerTest.prototype.setUp.call(this);
+
+    return new Promise(resolve => {
+      document.addEventListener('a11y-setup-complete', resolve);
+    });
+  },
+};
diff --git a/chrome/test/data/webui/settings/a11y/v3_a11y_browsertest.js b/chrome/test/data/webui/settings/a11y/v3_a11y_browsertest.js
new file mode 100644
index 0000000..520c7172
--- /dev/null
+++ b/chrome/test/data/webui/settings/a11y/v3_a11y_browsertest.js
@@ -0,0 +1,79 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// SettingsAccessibilityV3Test fixture.
+GEN_INCLUDE([
+  'settings_accessibility_v3_test.js',
+]);
+
+GEN('#include "build/branding_buildflags.h"');
+
+// TODO(crbug.com/1002627): This block prevents generation of a
+// link-in-text-block browser-test. This can be removed once the bug is
+// addressed, and usage should be replaced with
+// SettingsAccessibilityV3Test.axeOptions
+const axeOptionsExcludeLinkInTextBlock =
+    Object.assign({}, SettingsAccessibilityV3Test.axeOptions, {
+      'rules': Object.assign({}, SettingsAccessibilityV3Test.axeOptions.rules, {
+        'link-in-text-block': {enabled: false},
+      })
+    });
+
+const editDictionaryViolationFilter =
+    Object.assign({}, SettingsAccessibilityV3Test.violationFilter, {
+      // Excuse custom input elements.
+      'aria-valid-attr-value': function(nodeResult) {
+        const describerId = nodeResult.element.getAttribute('aria-describedby');
+        return describerId === '' && nodeResult.element.tagName == 'INPUT';
+      },
+      'tabindex': function(nodeResult) {
+        // TODO(crbug.com/808276): remove this exception when bug is fixed.
+        return nodeResult.element.getAttribute('tabindex') == '0';
+      },
+    });
+
+[[
+  'About', 'about_a11y_v3_test.js', {options: axeOptionsExcludeLinkInTextBlock}
+],
+ ['Accessibility', 'accessibility_a11y_v3_test.js'],
+ ['Basic', 'basic_a11y_v3_test.js'],
+ ['Passwords', 'passwords_a11y_v3_test.js'],
+].forEach(test => defineTest(...test));
+
+// Disable since the EDIT_DICTIONARY route does not exist on Mac.
+// TODO(crbug.com/1012370) flaky on Linux b/c assertTrue(!!languagesPage);
+// TODO(crbug.com/1012370) flaky on Win the same way
+GEN('#if !defined(OS_MACOSX) && !defined(OS_LINUX) && !defined(OS_WIN)');
+defineTest(
+    'EditDictionary', 'edit_dictionary_a11y_v3_test.js',
+    {filter: editDictionaryViolationFilter});
+GEN('#endif');
+
+function defineTest(testName, module, config) {
+  const className = `SettingsA11y${testName}V3`;
+  this[className] = class extends SettingsAccessibilityV3Test {
+    /** @override */
+    get browsePreload() {
+      return `chrome://settings/test_loader.html?module=settings/a11y/${
+          module}`;
+    }
+  };
+
+  const filter = config && config.filter ?
+      config.filter :
+      SettingsAccessibilityV3Test.violationFilter;
+  const options = config && config.options ?
+      config.options :
+      SettingsAccessibilityV3Test.axeOptions;
+  AccessibilityTest.define(className, {
+    /** @override */
+    name: testName,
+    /** @override */
+    axeOptions: options,
+    /** @override */
+    tests: {'All': function() {}},
+    /** @override */
+    violationFilter: filter,
+  });
+}
diff --git a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
index a8474e5..3cd6ee4f 100644
--- a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
+++ b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
@@ -357,6 +357,7 @@
       /** @type {?SettingsCrostiniPortForwarding} */
       let subpage;
       setup(async function() {
+        /*TODO(juwa): remove*/ console.log(`setting up ${this.test.title}`);
         setCrostiniPrefs(true, {
           forwardedPorts: [
             {
@@ -374,27 +375,47 @@
           ]
         });
 
+        /*TODO(juwa): remove*/ console.log(
+            `before flushAsync ${this.test.title}`);
         await flushAsync();
+        /*TODO(juwa): remove*/ console.log(
+            `after flushAsync ${this.test.title}`);
         settings.Router.getInstance().navigateTo(
             settings.routes.CROSTINI_PORT_FORWARDING);
 
+        /*TODO(juwa): remove*/ console.log(
+            `before flushAsync ${this.test.title}`);
         await flushAsync();
+        /*TODO(juwa): remove*/ console.log(
+            `after flushAsync ${this.test.title}`);
         subpage = crostiniPage.$$('settings-crostini-port-forwarding');
         assertTrue(!!subpage);
+        /*TODO(juwa): remove*/ console.log(`setup ${this.test.title}`);
       });
 
       test('Forwarded ports are shown', function() {
+        /*TODO(juwa): remove*/ console.log(`running ${this.test.title}`);
         // Extra list item for the titles.
         assertEquals(
             3, subpage.shadowRoot.querySelectorAll('.list-item').length);
+        /*TODO(juwa): remove*/ console.log(`ran ${this.test.title}`);
       });
 
       test('AddPortSuccess', async function() {
+        /*TODO(juwa): remove*/ console.log(`running ${this.test.title}`);
+        /*TODO(juwa): remove*/ console.log(
+            `before flushAsync ${this.test.title}`);
         await flushAsync();
+        /*TODO(juwa): remove*/ console.log(
+            `after flushAsync ${this.test.title}`);
         subpage = crostiniPage.$$('settings-crostini-port-forwarding');
         subpage.$$('#addPort cr-button').click();
 
+        /*TODO(juwa): remove*/ console.log(
+            `before flushAsync ${this.test.title}`);
         await flushAsync();
+        /*TODO(juwa): remove*/ console.log(
+            `after flushAsync ${this.test.title}`);
         subpage = subpage.$$('settings-crostini-add-port-dialog');
         const portNumberInput = subpage.$$('#portNumberInput');
         portNumberInput.value = '5000';
@@ -403,14 +424,24 @@
         subpage.$$('cr-dialog cr-button[id="continue"]').click();
         assertEquals(
             1, crostiniBrowserProxy.getCallCount('addCrostiniPortForward'));
+        /*TODO(juwa): remove*/ console.log(`ran ${this.test.title}`);
       });
 
       test('AddPortFail', async function() {
+        /*TODO(juwa): remove*/ console.log(`running ${this.test.title}`);
+        /*TODO(juwa): remove*/ console.log(
+            `before flushAsync ${this.test.title}`);
         await flushAsync();
+        /*TODO(juwa): remove*/ console.log(
+            `after flushAsync ${this.test.title}`);
         subpage = crostiniPage.$$('settings-crostini-port-forwarding');
         subpage.$$('#addPort cr-button').click();
 
+        /*TODO(juwa): remove*/ console.log(
+            `before flushAsync ${this.test.title}`);
         await flushAsync();
+        /*TODO(juwa): remove*/ console.log(
+            `after flushAsync ${this.test.title}`);
         subpage = subpage.$$('settings-crostini-add-port-dialog');
         const portNumberInput = subpage.$$('#portNumberInput');
         portNumberInput.value = 'INVALID_PORT_NUMBER';
@@ -427,21 +458,36 @@
         subpage.$$('cr-dialog cr-button[id="continue"]').click();
         assertEquals(
             1, crostiniBrowserProxy.getCallCount('addCrostiniPortForward'));
+        /*TODO(juwa): remove*/ console.log(`ran ${this.test.title}`);
       });
 
       test('AddPortCancel', async function() {
+        /*TODO(juwa): remove*/ console.log(`running ${this.test.title}`);
+        /*TODO(juwa): remove*/ console.log(
+            `before flushAsync ${this.test.title}`);
         await flushAsync();
+        /*TODO(juwa): remove*/ console.log(
+            `after flushAsync ${this.test.title}`);
         subpage = crostiniPage.$$('settings-crostini-port-forwarding');
         subpage.$$('#addPort cr-button').click();
 
+        /*TODO(juwa): remove*/ console.log(
+            `before flushAsync ${this.test.title}`);
         await flushAsync();
+        /*TODO(juwa): remove*/ console.log(
+            `after flushAsync ${this.test.title}`);
         subpage = subpage.$$('settings-crostini-add-port-dialog');
         subpage.$$('cr-dialog cr-button[id="cancel"]').click();
 
 
+        /*TODO(juwa): remove*/ console.log(
+            `before flushAsync ${this.test.title}`);
         await flushAsync();
+        /*TODO(juwa): remove*/ console.log(
+            `after flushAsync ${this.test.title}`);
         subpage = crostiniPage.$$('settings-crostini-port-forwarding');
         assertTrue(!!subpage);
+        /*TODO(juwa): remove*/ console.log(`ran ${this.test.title}`);
       });
     });
 
diff --git a/chrome/test/data/webui/settings/chromeos/device_page_tests.js b/chrome/test/data/webui/settings/chromeos/device_page_tests.js
index f36bf82..f17a6409 100644
--- a/chrome/test/data/webui/settings/chromeos/device_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/device_page_tests.js
@@ -73,8 +73,12 @@
     },
 
     /** @override */
-    setIdleBehavior: function(behavior) {
-      this.idleBehavior_ = behavior;
+    setIdleBehavior: function(behavior, whenOnAc) {
+      if (whenOnAc) {
+        this.acIdleBehavior_ = behavior;
+      } else {
+        this.batteryIdleBehavior_ = behavior;
+      }
     },
 
     /** @override */
@@ -469,18 +473,27 @@
     }
 
     /**
-     * @param {settings.IdleBehavior} idleBehavior
-     * @param {boolean} idleControlled
+     * @param {!Array<!settings.IdleBehavior>} possibleAcIdleBehaviors
+     * @param {!Array<!settings.IdleBehavior>} possibleBatteryIdleBehaviors
+     * @param {settings.IdleBehavior} currAcIdleBehavior
+     * @param {settings.IdleBehavior} currBatteryIdleBehavior
+     * @param {boolean} acIdleManaged
+     * @param {boolean} batteryIdleManaged
      * @param {settings.LidClosedBehavior} lidClosedBehavior
      * @param {boolean} lidClosedControlled
      * @param {boolean} hasLid
      */
     function sendPowerManagementSettings(
-        idleBehavior, idleControlled, lidClosedBehavior, lidClosedControlled,
-        hasLid) {
+        possibleAcIdleBehaviors, possibleBatteryIdleBehaviors,
+        currAcIdleBehavior, currBatteryIdleBehavior, acIdleManaged,
+        batteryIdleManaged, lidClosedBehavior, lidClosedControlled, hasLid) {
       cr.webUIListenerCallback('power-management-settings-changed', {
-        idleBehavior: idleBehavior,
-        idleControlled: idleControlled,
+        possibleAcIdleBehaviors: possibleAcIdleBehaviors,
+        possibleBatteryIdleBehaviors: possibleBatteryIdleBehaviors,
+        currentAcIdleBehavior: currAcIdleBehavior,
+        currentBatteryIdleBehavior: currBatteryIdleBehavior,
+        acIdleManaged: acIdleManaged,
+        batteryIdleManaged: batteryIdleManaged,
         lidClosedBehavior: lidClosedBehavior,
         lidClosedControlled: lidClosedControlled,
         hasLid: hasLid,
@@ -1010,7 +1023,7 @@
         let powerPage;
         let powerSourceRow;
         let powerSourceSelect;
-        let idleSelect;
+        let acIdleSelect;
         let lidClosedToggle;
 
         suiteSetup(function() {
@@ -1031,7 +1044,7 @@
                     settings.DevicePageBrowserProxyImpl.getInstance()
                         .updatePowerStatusCalled_);
 
-                idleSelect = assert(powerPage.$$('#idleSelect'));
+                acIdleSelect = assert(powerPage.$$('#acIdleSelect'));
                 lidClosedToggle = assert(powerPage.$$('#lidClosedToggle'));
 
                 assertEquals(
@@ -1039,8 +1052,19 @@
                     settings.DevicePageBrowserProxyImpl.getInstance()
                         .requestPowerManagementSettingsCalled_);
                 sendPowerManagementSettings(
+                    [
+                      settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                      settings.IdleBehavior.DISPLAY_OFF,
+                      settings.IdleBehavior.DISPLAY_ON
+                    ],
+                    [
+                      settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                      settings.IdleBehavior.DISPLAY_OFF,
+                      settings.IdleBehavior.DISPLAY_ON
+                    ],
                     settings.IdleBehavior.DISPLAY_OFF_SLEEP,
-                    false /* idleControlled */,
+                    settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                    false /* acIdleManaged */, false /* batteryIdleManaged */,
                     settings.LidClosedBehavior.SUSPEND,
                     false /* lidClosedControlled */, true /* hasLid */);
               });
@@ -1060,6 +1084,9 @@
 
           // Power source row is hidden since there's no battery.
           assertTrue(powerSourceRow.hidden);
+          // Idle settings while on battery should not be visible if the
+          // battery is not present.
+          assertEquals(null, powerPage.$$('#batteryIdleSettingBox'));
         });
 
         test('power sources', function() {
@@ -1135,24 +1162,31 @@
               settings.DevicePageBrowserProxyImpl.getInstance().powerSourceId_);
         });
 
-        test('set idle behavior', function() {
-          selectValue(idleSelect, settings.IdleBehavior.DISPLAY_ON);
+        test('set AC idle behavior', function() {
+          selectValue(acIdleSelect, settings.IdleBehavior.DISPLAY_ON);
           expectEquals(
               settings.IdleBehavior.DISPLAY_ON,
-              settings.DevicePageBrowserProxyImpl.getInstance().idleBehavior_);
-
-          selectValue(idleSelect, settings.IdleBehavior.DISPLAY_OFF);
-          expectEquals(
-              settings.IdleBehavior.DISPLAY_OFF,
-              settings.DevicePageBrowserProxyImpl.getInstance().idleBehavior_);
+              settings.DevicePageBrowserProxyImpl.getInstance()
+                  .acIdleBehavior_);
         });
 
         test('set lid behavior', function() {
           const sendLid = function(lidBehavior) {
             sendPowerManagementSettings(
-                settings.IdleBehavior.DISPLAY_OFF, false /* idleControlled */,
-                lidBehavior, false /* lidClosedControlled */,
-                true /* hasLid */);
+                [
+                  settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                  settings.IdleBehavior.DISPLAY_OFF,
+                  settings.IdleBehavior.DISPLAY_ON
+                ],
+                [
+                  settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                  settings.IdleBehavior.DISPLAY_OFF,
+                  settings.IdleBehavior.DISPLAY_ON
+                ],
+                settings.IdleBehavior.DISPLAY_OFF,
+                settings.IdleBehavior.DISPLAY_OFF, false /* acIdleManaged */,
+                false /* batteryIdleManaged */, lidBehavior,
+                false /* lidClosedControlled */, true /* hasLid */);
           };
 
           sendLid(settings.LidClosedBehavior.SUSPEND);
@@ -1177,9 +1211,33 @@
 
         test('display idle and lid behavior', function() {
           return new Promise(function(resolve) {
+                   // Indicate battery presence so that idle settings box while
+                   // on battery is visible.
+                   const batteryStatus = {
+                     present: true,
+                     charging: false,
+                     calculating: false,
+                     percent: 50,
+                     statusText: '5 hours left',
+                   };
+                   cr.webUIListenerCallback(
+                       'battery-status-changed',
+                       Object.assign({}, batteryStatus));
                    sendPowerManagementSettings(
+                       [
+                         settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                         settings.IdleBehavior.DISPLAY_OFF,
+                         settings.IdleBehavior.DISPLAY_ON
+                       ],
+                       [
+                         settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                         settings.IdleBehavior.DISPLAY_OFF,
+                         settings.IdleBehavior.DISPLAY_ON
+                       ],
                        settings.IdleBehavior.DISPLAY_ON,
-                       false /* idleControlled */,
+                       settings.IdleBehavior.DISPLAY_OFF,
+                       false /* acIdleManaged */,
+                       false /* batteryIdleManaged */,
                        settings.LidClosedBehavior.DO_NOTHING,
                        false /* lidClosedControlled */, true /* hasLid */);
                    powerPage.async(resolve);
@@ -1187,9 +1245,9 @@
               .then(function() {
                 expectEquals(
                     settings.IdleBehavior.DISPLAY_ON.toString(),
-                    idleSelect.value);
-                expectFalse(idleSelect.disabled);
-                expectEquals(null, powerPage.$$('#idleControlledIndicator'));
+                    acIdleSelect.value);
+                expectFalse(acIdleSelect.disabled);
+                expectEquals(null, powerPage.$$('#acIdleManagedIndicator'));
                 expectEquals(
                     loadTimeData.getString('powerLidSleepLabel'),
                     lidClosedToggle.label);
@@ -1198,8 +1256,19 @@
               })
               .then(function() {
                 sendPowerManagementSettings(
+                    [
+                      settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                      settings.IdleBehavior.DISPLAY_OFF,
+                      settings.IdleBehavior.DISPLAY_ON
+                    ],
+                    [
+                      settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                      settings.IdleBehavior.DISPLAY_OFF,
+                      settings.IdleBehavior.DISPLAY_ON
+                    ],
                     settings.IdleBehavior.DISPLAY_OFF,
-                    false /* idleControlled */,
+                    settings.IdleBehavior.DISPLAY_ON, false /* acIdleManaged */,
+                    false /* batteryIdleManaged */,
                     settings.LidClosedBehavior.SUSPEND,
                     false /* lidClosedControlled */, true /* hasLid */);
                 return new Promise(function(resolve) {
@@ -1207,11 +1276,19 @@
                 });
               })
               .then(function() {
+                const batteryIdleSelect =
+                    assert(powerPage.$$('#batteryIdleSelect'));
                 expectEquals(
                     settings.IdleBehavior.DISPLAY_OFF.toString(),
-                    idleSelect.value);
-                expectFalse(idleSelect.disabled);
-                expectEquals(null, powerPage.$$('#idleControlledIndicator'));
+                    acIdleSelect.value);
+                expectEquals(
+                    settings.IdleBehavior.DISPLAY_ON.toString(),
+                    batteryIdleSelect.value);
+                expectFalse(acIdleSelect.disabled);
+                expectFalse(batteryIdleSelect.disabled);
+                expectEquals(null, powerPage.$$('#acIdleManagedIndicator'));
+                expectEquals(
+                    null, powerPage.$$('#batteryIdleManagedIndicator'));
                 expectEquals(
                     loadTimeData.getString('powerLidSleepLabel'),
                     lidClosedToggle.label);
@@ -1220,21 +1297,44 @@
               });
         });
 
-        test('display controlled idle and lid behavior', function() {
-          // When settings are controlled, the controls should be disabled and
+        test('display managed idle and lid behavior', function() {
+          // When settings are managed, the controls should be disabled and
           // the indicators should be shown.
           return new Promise(function(resolve) {
+                   // Indicate battery presence so that idle settings box while
+                   // on battery is visible.
+                   const batteryStatus = {
+                     present: true,
+                     charging: false,
+                     calculating: false,
+                     percent: 50,
+                     statusText: '5 hours left',
+                   };
+                   cr.webUIListenerCallback(
+                       'battery-status-changed',
+                       Object.assign({}, batteryStatus));
                    sendPowerManagementSettings(
-                       settings.IdleBehavior.OTHER, true /* idleControlled */,
+                       [settings.IdleBehavior.OTHER],
+                       [settings.IdleBehavior.OTHER],
+                       settings.IdleBehavior.OTHER, settings.IdleBehavior.OTHER,
+                       true /* acIdleManaged */, true /* batteryIdleManaged */,
                        settings.LidClosedBehavior.SHUT_DOWN,
                        true /* lidClosedControlled */, true /* hasLid */);
                    powerPage.async(resolve);
                  })
               .then(function() {
+                const batteryIdleSelect =
+                    assert(powerPage.$$('#batteryIdleSelect'));
                 expectEquals(
-                    settings.IdleBehavior.OTHER.toString(), idleSelect.value);
-                expectTrue(idleSelect.disabled);
-                expectNotEquals(null, powerPage.$$('#idleControlledIndicator'));
+                    settings.IdleBehavior.OTHER.toString(), acIdleSelect.value);
+                expectEquals(
+                    settings.IdleBehavior.OTHER.toString(),
+                    batteryIdleSelect.value);
+                expectTrue(acIdleSelect.disabled);
+                expectTrue(batteryIdleSelect.disabled);
+                expectNotEquals(null, powerPage.$$('#acIdleManagedIndicator'));
+                expectNotEquals(
+                    null, powerPage.$$('#batteryIdleManagedIndicator'));
                 expectEquals(
                     loadTimeData.getString('powerLidShutDownLabel'),
                     lidClosedToggle.label);
@@ -1243,8 +1343,11 @@
               })
               .then(function() {
                 sendPowerManagementSettings(
+                    [settings.IdleBehavior.DISPLAY_OFF],
+                    [settings.IdleBehavior.DISPLAY_OFF],
                     settings.IdleBehavior.DISPLAY_OFF,
-                    true /* idleControlled */,
+                    settings.IdleBehavior.DISPLAY_OFF,
+                    false /* acIdleManaged */, false /* batteryIdleManaged */,
                     settings.LidClosedBehavior.STOP_SESSION,
                     true /* lidClosedControlled */, true /* hasLid */);
                 return new Promise(function(resolve) {
@@ -1252,11 +1355,19 @@
                 });
               })
               .then(function() {
+                const batteryIdleSelect =
+                    assert(powerPage.$$('#batteryIdleSelect'));
                 expectEquals(
                     settings.IdleBehavior.DISPLAY_OFF.toString(),
-                    idleSelect.value);
-                expectTrue(idleSelect.disabled);
-                expectNotEquals(null, powerPage.$$('#idleControlledIndicator'));
+                    acIdleSelect.value);
+                expectEquals(
+                    settings.IdleBehavior.DISPLAY_OFF.toString(),
+                    batteryIdleSelect.value);
+                expectTrue(acIdleSelect.disabled);
+                expectTrue(batteryIdleSelect.disabled);
+                expectEquals(null, powerPage.$$('#acIdleManagedIndicator'));
+                expectEquals(
+                    null, powerPage.$$('#batteryIdleManagedIndicator'));
                 expectEquals(
                     loadTimeData.getString('powerLidSignOutLabel'),
                     lidClosedToggle.label);
@@ -1269,8 +1380,20 @@
           return new Promise(function(resolve) {
                    expectFalse(powerPage.$$('#lidClosedToggle').hidden);
                    sendPowerManagementSettings(
+                       [
+                         settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                         settings.IdleBehavior.DISPLAY_OFF,
+                         settings.IdleBehavior.DISPLAY_ON
+                       ],
+                       [
+                         settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                         settings.IdleBehavior.DISPLAY_OFF,
+                         settings.IdleBehavior.DISPLAY_ON
+                       ],
                        settings.IdleBehavior.DISPLAY_OFF_SLEEP,
-                       false /* idleControlled */,
+                       settings.IdleBehavior.DISPLAY_OFF_SLEEP,
+                       false /* acIdleManaged */,
+                       false /* batteryIdleManaged */,
                        settings.LidClosedBehavior.SUSPEND,
                        false /* lidClosedControlled */, false /* hasLid */);
                    powerPage.async(resolve);
@@ -1279,6 +1402,28 @@
                 expectTrue(powerPage.$$('#lidClosedToggle').hidden);
               });
         });
+
+        test(
+            'hide display controlled battery idle behavior when battery not present',
+            function() {
+              return new Promise(function(resolve) {
+                       const batteryStatus = {
+                         present: false,
+                         charging: false,
+                         calculating: false,
+                         percent: -1,
+                         statusText: '',
+                       };
+                       cr.webUIListenerCallback(
+                           'battery-status-changed',
+                           Object.assign({}, batteryStatus));
+                       Polymer.dom.flush();
+                       powerPage.async(resolve);
+                     })
+                  .then(function() {
+                    expectEquals(null, powerPage.$$('#batteryIdleSettingBox'));
+                  });
+            });
       });
     });
 
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
index 21e85c5..d036630 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -490,10 +490,9 @@
   mocha.grep('SubPageDefault').run();
 });
 
-TEST_F(
-    'OSSettingsCrostiniPageTest', 'DISABLED_SubPagePortForwarding', function() {
-      mocha.grep('SubPagePortForwarding').run();
-    });
+TEST_F('OSSettingsCrostiniPageTest', 'SubPagePortForwarding', function() {
+  mocha.grep('SubPagePortForwarding').run();
+});
 
 TEST_F('OSSettingsCrostiniPageTest', 'DiskResize', function() {
   mocha.grep('DiskResize').run();
diff --git a/chromecast/browser/webview/client/BUILD.gn b/chromecast/browser/webview/client/BUILD.gn
index 598ce32..a621015 100644
--- a/chromecast/browser/webview/client/BUILD.gn
+++ b/chromecast/browser/webview/client/BUILD.gn
@@ -15,6 +15,8 @@
     "//components/exo/wayland:client_support",
     "//skia",
     "//third_party/wayland:wayland_client",
+    "//ui/events:event_constants",
+    "//ui/events/types:headers",
     "//ui/gl",
   ]
 }
diff --git a/chromecast/browser/webview/client/webview.cc b/chromecast/browser/webview/client/webview.cc
index 038b7e8..59e21e6 100644
--- a/chromecast/browser/webview/client/webview.cc
+++ b/chromecast/browser/webview/client/webview.cc
@@ -13,6 +13,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
 #include "chromecast/browser/webview/proto/webview.pb.h"
 #include "third_party/grpc/src/include/grpcpp/grpcpp.h"
 #include "third_party/skia/include/gpu/GrContext.h"
@@ -47,6 +48,8 @@
 
 }  // namespace
 
+using chromecast::webview::InputEvent;
+using chromecast::webview::TouchInput;
 using chromecast::webview::WebviewRequest;
 using chromecast::webview::WebviewResponse;
 
@@ -182,6 +185,34 @@
   webviews_.erase(id);
 }
 
+void WebviewClient::HandleDown(void* data,
+                               struct wl_touch* wl_touch,
+                               uint32_t serial,
+                               uint32_t time,
+                               struct wl_surface* surface,
+                               int32_t id,
+                               wl_fixed_t x,
+                               wl_fixed_t y) {
+  gfx::Point touch_point(wl_fixed_to_int(x), wl_fixed_to_int(y));
+
+  auto iter = std::find_if(
+      webviews_.begin(), webviews_.end(),
+      [surface](const std::pair<const int, std::unique_ptr<Webview>>& pair) {
+        const auto& webview = pair.second;
+        return webview->surface.get() == surface;
+      });
+  if (iter == webviews_.end()) {
+    focused_webview_ = nullptr;
+    return;
+  }
+
+  const Webview* webview = iter->second.get();
+  focused_webview_ = webview;
+  SendTouchInput(focused_webview_, touch_point.x(), touch_point.y(),
+                 ui::ET_TOUCH_PRESSED, time, id);
+  points_[id] = touch_point;
+}
+
 void WebviewClient::HandleMode(void* data,
                                struct wl_output* wl_output,
                                uint32_t flags,
@@ -220,6 +251,34 @@
   wl_surface_set_input_region(surface_.get(), opaque_region.get());
 }
 
+void WebviewClient::HandleMotion(void* data,
+                                 struct wl_touch* wl_touch,
+                                 uint32_t time,
+                                 int32_t id,
+                                 wl_fixed_t x,
+                                 wl_fixed_t y) {
+  if (!focused_webview_)
+    return;
+  gfx::Point& touch_point = points_[id];
+  touch_point.set_x(wl_fixed_to_int(x));
+  touch_point.set_y(wl_fixed_to_int(y));
+  SendTouchInput(focused_webview_, touch_point.x(), touch_point.y(),
+                 ui::ET_TOUCH_MOVED, time, id);
+}
+
+void WebviewClient::HandleUp(void* data,
+                             struct wl_touch* wl_touch,
+                             uint32_t serial,
+                             uint32_t time,
+                             int32_t id) {
+  if (!focused_webview_)
+    return;
+  const gfx::Point& touch_point = points_[id];
+  SendTouchInput(focused_webview_, touch_point.x(), touch_point.y(),
+                 ui::ET_TOUCH_RELEASED, time, id);
+  points_.erase(id);
+}
+
 void WebviewClient::InputCallback() {
   std::string request;
   getline(std::cin, request);
@@ -337,6 +396,32 @@
       CreateBuffer(gfx::Size(width, height), drm_format_, bo_usage_);
 }
 
+void WebviewClient::SendTouchInput(const Webview* webview,
+                                   int x,
+                                   int y,
+                                   ui::EventType event_type,
+                                   uint32_t time,
+                                   int32_t id) {
+  auto touch_input = std::make_unique<TouchInput>();
+  touch_input->set_x(x);
+  touch_input->set_y(y);
+  touch_input->set_root_x(x);
+  touch_input->set_root_y(y);
+  touch_input->set_pointer_type(
+      static_cast<int>(ui::EventPointerType::POINTER_TYPE_TOUCH));
+  touch_input->set_pointer_id(id);
+
+  auto input_event = std::make_unique<InputEvent>();
+  input_event->set_event_type(event_type);
+  input_event->set_timestamp(time * base::Time::kMicrosecondsPerMillisecond);
+  input_event->set_allocated_touch(touch_input.release());
+
+  WebviewRequest input_request;
+  input_request.set_allocated_input(input_event.release());
+  if (!webview->client->Write(input_request))
+    LOG(ERROR) << "Input request failed";
+}
+
 void WebviewClient::SetPosition(const std::vector<std::string>& tokens) {
   int id, x, y;
   if (tokens.size() != 4 || !base::StringToInt(tokens[0], &id) ||
diff --git a/chromecast/browser/webview/client/webview.h b/chromecast/browser/webview/client/webview.h
index 7ac400d..a36cf4c 100644
--- a/chromecast/browser/webview/client/webview.h
+++ b/chromecast/browser/webview/client/webview.h
@@ -15,6 +15,9 @@
 #include "chromecast/browser/webview/proto/webview.grpc.pb.h"
 #include "components/exo/wayland/clients/client_base.h"
 #include "third_party/grpc/src/include/grpcpp/grpcpp.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/types/event_type.h"
+#include "ui/gfx/geometry/point.h"
 
 namespace chromecast {
 namespace client {
@@ -50,17 +53,42 @@
   void AllocateBuffers(const InitParams& params);
   void CreateWebview(const std::vector<std::string>& tokens);
   void DestroyWebview(const std::vector<std::string>& tokens);
+  void HandleDown(void* data,
+                  struct wl_touch* wl_touch,
+                  uint32_t serial,
+                  uint32_t time,
+                  struct wl_surface* surface,
+                  int32_t id,
+                  wl_fixed_t x,
+                  wl_fixed_t y) override;
   void HandleMode(void* data,
                   struct wl_output* wl_output,
                   uint32_t flags,
                   int32_t width,
                   int32_t height,
                   int32_t refresh) override;
+  void HandleMotion(void* data,
+                    struct wl_touch* wl_touch,
+                    uint32_t time,
+                    int32_t id,
+                    wl_fixed_t x,
+                    wl_fixed_t y) override;
+  void HandleUp(void* data,
+                struct wl_touch* wl_touch,
+                uint32_t serial,
+                uint32_t time,
+                int32_t id) override;
   void InputCallback();
   void ListActiveWebviews();
   void Paint();
   void SendNavigationRequest(const std::vector<std::string>& tokens);
   void SendResizeRequest(const std::vector<std::string>& tokens);
+  void SendTouchInput(const Webview* webview,
+                      int x,
+                      int y,
+                      ui::EventType event_type,
+                      uint32_t time,
+                      int32_t id);
   void SetPosition(const std::vector<std::string>& tokens);
   void TakeExclusiveAccess();
   void WlDisplayCallback();
@@ -68,7 +96,9 @@
   int32_t drm_format_ = 0;
   int32_t bo_usage_ = 0;
 
+  const Webview* focused_webview_;
   std::map<int, std::unique_ptr<Webview>> webviews_;
+  std::map<int32_t, gfx::Point> points_;
 
   std::unique_ptr<wl_callback> frame_callback_;
   std::vector<std::unique_ptr<BufferCallback>> buffer_callbacks_;
diff --git a/chromeos/network/network_configuration_handler.cc b/chromeos/network/network_configuration_handler.cc
index 448ad881..f36d72b 100644
--- a/chromeos/network/network_configuration_handler.cc
+++ b/chromeos/network/network_configuration_handler.cc
@@ -369,13 +369,12 @@
   }
 
   LogConfigProperties("Configure", type, *properties_to_set);
-
   std::unique_ptr<base::DictionaryValue> properties_copy(
       properties_to_set->DeepCopy());
   manager->ConfigureServiceForProfile(
       dbus::ObjectPath(profile_path), *properties_to_set,
       base::Bind(&NetworkConfigurationHandler::ConfigurationCompleted,
-                 weak_ptr_factory_.GetWeakPtr(), profile_path,
+                 weak_ptr_factory_.GetWeakPtr(), profile_path, guid,
                  base::Passed(&properties_copy), callback),
       base::Bind(&NetworkConfigurationHandler::ConfigurationFailed,
                  weak_ptr_factory_.GetWeakPtr(), error_callback));
@@ -520,6 +519,7 @@
 
 void NetworkConfigurationHandler::ConfigurationCompleted(
     const std::string& profile_path,
+    const std::string& guid,
     std::unique_ptr<base::DictionaryValue> configure_properties,
     const network_handler::ServiceResultCallback& callback,
     const dbus::ObjectPath& service_path) {
@@ -532,6 +532,9 @@
   // the newly configured properties immediately, request an update here.
   network_state_handler_->RequestUpdateForNetwork(service_path.value());
 
+  for (auto& observer : observers_)
+    observer.OnConfigurationCreated(service_path.value(), guid);
+
   if (callback.is_null())
     return;
 
diff --git a/chromeos/network/network_configuration_handler.h b/chromeos/network/network_configuration_handler.h
index 36a44c3..fa4f7b6 100644
--- a/chromeos/network/network_configuration_handler.h
+++ b/chromeos/network/network_configuration_handler.h
@@ -151,6 +151,7 @@
   // state (NetworkStateHandler) to update before triggering the callback.
   void ConfigurationCompleted(
       const std::string& profile_path,
+      const std::string& guid,
       std::unique_ptr<base::DictionaryValue> configure_properties,
       const network_handler::ServiceResultCallback& callback,
       const dbus::ObjectPath& service_path);
diff --git a/chromeos/network/network_configuration_handler_unittest.cc b/chromeos/network/network_configuration_handler_unittest.cc
index 4992b70..274ab6e 100644
--- a/chromeos/network/network_configuration_handler_unittest.cc
+++ b/chromeos/network/network_configuration_handler_unittest.cc
@@ -95,6 +95,11 @@
   TestNetworkConfigurationObserver() = default;
 
   // NetworkConfigurationObserver
+  void OnConfigurationCreated(const std::string& service_path,
+                              const std::string& guid) override {
+    created_configurations_[service_path] = guid;
+  }
+
   void OnBeforeConfigurationRemoved(const std::string& service_path,
                                     const std::string& guid) override {
     ASSERT_EQ(before_remove_configurations_.end(),
@@ -115,6 +120,11 @@
     updated_configurations_[service_path] = guid;
   }
 
+  bool HasCreatedConfiguration(const std::string& service_path) {
+    return created_configurations_.find(service_path) !=
+           created_configurations_.end();
+  }
+
   bool HasCalledBeforeRemoveConfiguration(const std::string& service_path) {
     return before_remove_configurations_.find(service_path) !=
            before_remove_configurations_.end();
@@ -131,6 +141,7 @@
   }
 
  private:
+  std::map<std::string, std::string> created_configurations_;
   std::map<std::string, std::string> before_remove_configurations_;
   std::map<std::string, std::string> removed_configurations_;
   std::map<std::string, std::string> updated_configurations_;
@@ -671,6 +682,22 @@
   EXPECT_EQ(NetworkProfileHandler::GetSharedProfilePath(), actual_profile);
 }
 
+TEST_F(NetworkConfigurationHandlerTest, NetworkConfigurationObserver_Added) {
+  const std::string service_path("/service/test_wifi");
+
+  auto network_configuration_observer =
+      std::make_unique<TestNetworkConfigurationObserver>();
+  network_configuration_handler_->AddObserver(
+      network_configuration_observer.get());
+  CreateTestConfiguration(service_path, shill::kTypeWifi);
+
+  EXPECT_TRUE(network_configuration_observer->HasCreatedConfiguration(
+      create_service_path_));
+
+  network_configuration_handler_->RemoveObserver(
+      network_configuration_observer.get());
+}
+
 TEST_F(NetworkConfigurationHandlerTest, NetworkConfigurationObserver_Removed) {
   const std::string service_path("/service/test_wifi");
 
diff --git a/chromeos/network/network_configuration_observer.cc b/chromeos/network/network_configuration_observer.cc
index f810947..d1b1adba 100644
--- a/chromeos/network/network_configuration_observer.cc
+++ b/chromeos/network/network_configuration_observer.cc
@@ -10,6 +10,10 @@
 
 NetworkConfigurationObserver::~NetworkConfigurationObserver() = default;
 
+void NetworkConfigurationObserver::OnConfigurationCreated(
+    const std::string& service_path,
+    const std::string& guid) {}
+
 void NetworkConfigurationObserver::OnConfigurationModified(
     const std::string& service_path,
     const std::string& guid,
diff --git a/chromeos/network/network_configuration_observer.h b/chromeos/network/network_configuration_observer.h
index 4570268..0954497 100644
--- a/chromeos/network/network_configuration_observer.h
+++ b/chromeos/network/network_configuration_observer.h
@@ -19,6 +19,10 @@
 // Observer class for network configuration events (remove only).
 class COMPONENT_EXPORT(CHROMEOS_NETWORK) NetworkConfigurationObserver {
  public:
+  // Called after a new network configuration is created successfully.
+  virtual void OnConfigurationCreated(const std::string& service_path,
+                                      const std::string& guid);
+
   // Called whenever properties on a network configuration are modified.
   virtual void OnConfigurationModified(const std::string& service_path,
                                        const std::string& guid,
diff --git a/chromeos/network/network_metadata_store.cc b/chromeos/network/network_metadata_store.cc
index 3100a15..5c30871 100644
--- a/chromeos/network/network_metadata_store.cc
+++ b/chromeos/network/network_metadata_store.cc
@@ -23,6 +23,7 @@
 const char kNetworkMetadataPref[] = "network_metadata";
 const char kLastConnectedTimestampPref[] = "last_connected_timestamp";
 const char kIsFromSync[] = "is_from_sync";
+const char kIsCreatedByUser[] = "is_created_by_user";
 
 std::string GetPath(const std::string& guid, const std::string& subkey) {
   return base::StringPrintf("%s.%s", guid.c_str(), subkey.c_str());
@@ -83,6 +84,12 @@
   }
 }
 
+void NetworkMetadataStore::OnConfigurationCreated(
+    const std::string& service_path,
+    const std::string& guid) {
+  SetPref(guid, kIsCreatedByUser, base::Value(true));
+}
+
 void NetworkMetadataStore::OnConfigurationModified(
     const std::string& service_path,
     const std::string& guid,
@@ -162,6 +169,16 @@
   return is_from_sync->GetBool();
 }
 
+bool NetworkMetadataStore::GetIsCreatedByUser(const std::string& network_guid) {
+  const base::Value* is_created_by_user =
+      GetPref(network_guid, kIsCreatedByUser);
+  if (!is_created_by_user) {
+    return false;
+  }
+
+  return is_created_by_user->GetBool();
+}
+
 void NetworkMetadataStore::SetPref(const std::string& network_guid,
                                    const std::string& key,
                                    base::Value value) {
diff --git a/chromeos/network/network_metadata_store.h b/chromeos/network/network_metadata_store.h
index 0ad50125..012f2ef 100644
--- a/chromeos/network/network_metadata_store.h
+++ b/chromeos/network/network_metadata_store.h
@@ -52,6 +52,8 @@
   void ConnectSucceeded(const std::string& service_path) override;
 
   // NetworkConfigurationObserver::
+  void OnConfigurationCreated(const std::string& service_path,
+                              const std::string& guid) override;
   void OnConfigurationModified(const std::string& service_path,
                                const std::string& guid,
                                base::DictionaryValue* set_properties) override;
@@ -68,6 +70,9 @@
   // Networks which were added directly from sync data will return true.
   bool GetIsConfiguredBySync(const std::string& network_guid);
 
+  // Networks which were created by the logged in user will return true.
+  bool GetIsCreatedByUser(const std::string& network_guid);
+
   // Manage observers.
   void AddObserver(NetworkMetadataObserver* observer);
   void RemoveObserver(NetworkMetadataObserver* observer);
diff --git a/chromeos/network/network_metadata_store_unittest.cc b/chromeos/network/network_metadata_store_unittest.cc
index 4252d4e7..7263d0a 100644
--- a/chromeos/network/network_metadata_store_unittest.cc
+++ b/chromeos/network/network_metadata_store_unittest.cc
@@ -137,6 +137,14 @@
   ASSERT_TRUE(metadata_observer()->HasConnected(kGuid));
 }
 
+TEST_F(NetworkMetadataStoreTest, ConfigurationCreated) {
+  std::string service_path = ConfigureService(kConfigWifi0Connectable);
+  metadata_store()->OnConfigurationCreated(service_path, kGuid);
+  base::RunLoop().RunUntilIdle();
+
+  ASSERT_TRUE(metadata_store()->GetIsCreatedByUser(kGuid));
+}
+
 TEST_F(NetworkMetadataStoreTest, ConfigurationUpdated) {
   std::string service_path = ConfigureService(kConfigWifi0Connectable);
   network_connection_handler()->ConnectToNetwork(
diff --git a/components/arc/ime/arc_ime_service.cc b/components/arc/ime/arc_ime_service.cc
index 5e312b0..a194200b 100644
--- a/components/arc/ime/arc_ime_service.cc
+++ b/components/arc/ime/arc_ime_service.cc
@@ -299,11 +299,7 @@
     ui::TextInputType type,
     bool is_personalized_learning_allowed,
     int flags) {
-  // The focus is on a non-ARC window. This method can be called even When a
-  // text input on a non-ARC window is focused because there is a dummy input
-  // view in Android side which is synchronized with the text input on the
-  // non-ARC window.
-  if (focused_arc_window_ == nullptr)
+  if (!ShouldSendUpdateToInputMethod())
     return;
 
   if (ime_type_ == type &&
@@ -332,11 +328,7 @@
 
 void ArcImeService::OnCursorRectChanged(const gfx::Rect& rect,
                                         bool is_screen_coordinates) {
-  // The focus is on a non-ARC window. This method can be called even when a
-  // text input on a non-ARC window is focused because there is a dummy input
-  // view in Android side which is synchronized with the text input on the
-  // non-ARC window.
-  if (focused_arc_window_ == nullptr)
+  if (!ShouldSendUpdateToInputMethod())
     return;
 
   InvalidateSurroundingTextAndSelectionRange();
@@ -349,11 +341,7 @@
 }
 
 void ArcImeService::OnCancelComposition() {
-  // The focus is on a non-ARC window. This method can be called even when a
-  // text input on a non-ARC window is focused because there is a dummy input
-  // view in Android side which is synchronized with the text input on the
-  // non-ARC window.
-  if (focused_arc_window_ == nullptr)
+  if (!ShouldSendUpdateToInputMethod())
     return;
 
   InvalidateSurroundingTextAndSelectionRange();
@@ -363,11 +351,7 @@
 }
 
 void ArcImeService::ShowVirtualKeyboardIfEnabled() {
-  // The focus is on a non-ARC window. This method can be called even when a
-  // text input on a non-ARC window is focused because there is a dummy input
-  // view in Android side which is synchronized with the text input on the
-  // non-ARC window.
-  if (focused_arc_window_ == nullptr)
+  if (!ShouldSendUpdateToInputMethod())
     return;
 
   ui::InputMethod* const input_method = GetInputMethod();
@@ -382,11 +366,7 @@
     const base::string16& text_in_range,
     const gfx::Range& selection_range,
     bool is_screen_coordinates) {
-  // The focus is on a non-ARC window. This method can be called even when a
-  // text input on a non-ARC window is focused because there is a dummy input
-  // view in Android side which is synchronized with the text input on the
-  // non-ARC window.
-  if (focused_arc_window_ == nullptr)
+  if (!ShouldSendUpdateToInputMethod())
     return;
 
   text_range_ = text_range;
@@ -675,4 +655,12 @@
   return true;
 }
 
+bool ArcImeService::ShouldSendUpdateToInputMethod() const {
+  // New text input state received from Android should not be sent to
+  // InputMethod when the focus is on a non-ARC window. Text input state updates
+  // can be sent from Android anytime because there is a dummy input view in
+  // Android which is synchronized with the text input on a non-ARC window.
+  return focused_arc_window_ != nullptr;
+}
+
 }  // namespace arc
diff --git a/components/arc/ime/arc_ime_service.h b/components/arc/ime/arc_ime_service.h
index 118858c3..bc12839 100644
--- a/components/arc/ime/arc_ime_service.h
+++ b/components/arc/ime/arc_ime_service.h
@@ -170,6 +170,10 @@
   // updates |cursor_rect_|. Returns whether or not the stored value changed.
   bool UpdateCursorRect(const gfx::Rect& rect, bool is_screen_coordinates);
 
+  // Returns true if this TextInputClient is active and incoming input state
+  // from Android is valid.
+  bool ShouldSendUpdateToInputMethod() const;
+
   std::unique_ptr<ArcImeBridge> ime_bridge_;
   std::unique_ptr<ArcWindowDelegate> arc_window_delegate_;
   ui::TextInputType ime_type_;
diff --git a/components/arc/ime/arc_ime_service_unittest.cc b/components/arc/ime/arc_ime_service_unittest.cc
index cb9028e..f38b5efd 100644
--- a/components/arc/ime/arc_ime_service_unittest.cc
+++ b/components/arc/ime/arc_ime_service_unittest.cc
@@ -77,7 +77,8 @@
         count_show_ime_if_needed_(0),
         count_cancel_composition_(0),
         count_set_focused_text_input_client_(0),
-        count_on_text_input_type_changed_(0) {}
+        count_on_text_input_type_changed_(0),
+        count_on_caret_bounds_changed_(0) {}
 
   void SetFocusedTextInputClient(ui::TextInputClient* client) override {
     count_set_focused_text_input_client_++;
@@ -104,6 +105,10 @@
     count_on_text_input_type_changed_++;
   }
 
+  void OnCaretBoundsChanged(const ui::TextInputClient* client) override {
+    count_on_caret_bounds_changed_++;
+  }
+
   int count_show_ime_if_needed() const {
     return count_show_ime_if_needed_;
   }
@@ -120,12 +125,17 @@
     return count_on_text_input_type_changed_;
   }
 
+  int count_on_caret_bounds_changed() const {
+    return count_on_caret_bounds_changed_;
+  }
+
  private:
   ui::TextInputClient* client_;
   int count_show_ime_if_needed_;
   int count_cancel_composition_;
   int count_set_focused_text_input_client_;
   int count_on_text_input_type_changed_;
+  int count_on_caret_bounds_changed_;
 };
 
 // Helper class for testing the window focus tracking feature of ArcImeService,
@@ -478,4 +488,24 @@
   EXPECT_EQ(3, fake_input_method_->count_on_text_input_type_changed());
 }
 
+TEST_F(ArcImeServiceTest, DoNothingIfArcWindowIsNotFocused) {
+  ASSERT_EQ(0, fake_input_method_->count_show_ime_if_needed());
+  ASSERT_EQ(0, fake_input_method_->count_on_text_input_type_changed());
+  ASSERT_EQ(0, fake_input_method_->count_on_caret_bounds_changed());
+  ASSERT_EQ(0, fake_input_method_->count_cancel_composition());
+
+  instance_->OnWindowFocused(nullptr, nullptr);
+
+  const gfx::Rect cursor_rect(10, 20, 30, 40);
+  instance_->OnTextInputTypeChanged(ui::TEXT_INPUT_TYPE_TEXT, true,
+                                    mojom::TEXT_INPUT_FLAG_NONE);
+  instance_->OnCursorRectChanged(cursor_rect, true);
+  instance_->OnCancelComposition();
+
+  EXPECT_EQ(0, fake_input_method_->count_show_ime_if_needed());
+  EXPECT_EQ(0, fake_input_method_->count_on_text_input_type_changed());
+  EXPECT_EQ(0, fake_input_method_->count_on_caret_bounds_changed());
+  EXPECT_EQ(0, fake_input_method_->count_cancel_composition());
+}
+
 }  // namespace arc
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index f825ec3..281e49f7 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -163,14 +163,15 @@
   wl_global_create(wl_display_.get(), &zcr_gaming_input_v2_interface, 1,
                    display_, bind_gaming_input);
   wl_global_create(wl_display_.get(), &zcr_keyboard_configuration_v1_interface,
-                   kZcrKeyboardConfigurationVersion, display_,
+                   zcr_keyboard_configuration_v1_interface.version, display_,
                    bind_keyboard_configuration);
   wl_global_create(wl_display_.get(), &zcr_keyboard_extension_v1_interface, 1,
                    display_, bind_keyboard_extension);
   wl_global_create(wl_display_.get(), &zcr_notification_shell_v1_interface, 1,
                    display_, bind_notification_shell);
   wl_global_create(wl_display_.get(), &zcr_remote_shell_v1_interface,
-                   kZcrRemoteShellVersion, display_, bind_remote_shell);
+                   zcr_remote_shell_v1_interface.version, display_,
+                   bind_remote_shell);
   wl_global_create(wl_display_.get(), &zcr_stylus_tools_v1_interface, 1,
                    display_, bind_stylus_tools);
   wl_global_create(wl_display_.get(),
diff --git a/components/exo/wayland/zcr_keyboard_configuration.cc b/components/exo/wayland/zcr_keyboard_configuration.cc
index c0aea5f5..ffc9df2b 100644
--- a/components/exo/wayland/zcr_keyboard_configuration.cc
+++ b/components/exo/wayland/zcr_keyboard_configuration.cc
@@ -127,7 +127,9 @@
                                  uint32_t id) {
   wl_resource* resource = wl_resource_create(
       client, &zcr_keyboard_configuration_v1_interface,
-      std::min(version, kZcrKeyboardConfigurationVersion), id);
+      std::min<uint32_t>(version,
+                         zcr_keyboard_configuration_v1_interface.version),
+      id);
   wl_resource_set_implementation(
       resource, &keyboard_configuration_implementation, data, nullptr);
 }
diff --git a/components/exo/wayland/zcr_keyboard_configuration.h b/components/exo/wayland/zcr_keyboard_configuration.h
index a0af82c..9c0b87d 100644
--- a/components/exo/wayland/zcr_keyboard_configuration.h
+++ b/components/exo/wayland/zcr_keyboard_configuration.h
@@ -12,8 +12,6 @@
 namespace exo {
 namespace wayland {
 
-constexpr uint32_t kZcrKeyboardConfigurationVersion = 2;
-
 void bind_keyboard_configuration(wl_client* client,
                                  void* data,
                                  uint32_t version,
diff --git a/components/exo/wayland/zcr_remote_shell.cc b/components/exo/wayland/zcr_remote_shell.cc
index 3feadda..7aa199e 100644
--- a/components/exo/wayland/zcr_remote_shell.cc
+++ b/components/exo/wayland/zcr_remote_shell.cc
@@ -1318,9 +1318,9 @@
                        void* data,
                        uint32_t version,
                        uint32_t id) {
-  wl_resource* resource =
-      wl_resource_create(client, &zcr_remote_shell_v1_interface,
-                         std::min(version, kZcrRemoteShellVersion), id);
+  wl_resource* resource = wl_resource_create(
+      client, &zcr_remote_shell_v1_interface,
+      std::min<uint32_t>(version, zcr_remote_shell_v1_interface.version), id);
 
   SetImplementation(resource, &remote_shell_implementation,
                     std::make_unique<WaylandRemoteShell>(
diff --git a/components/exo/wayland/zcr_remote_shell.h b/components/exo/wayland/zcr_remote_shell.h
index b26fda79..8214a6af 100644
--- a/components/exo/wayland/zcr_remote_shell.h
+++ b/components/exo/wayland/zcr_remote_shell.h
@@ -22,8 +22,6 @@
 namespace exo {
 namespace wayland {
 
-constexpr uint32_t kZcrRemoteShellVersion = 27;
-
 void bind_remote_shell(wl_client* client,
                        void* data,
                        uint32_t version,
diff --git a/components/feed/core/v2/BUILD.gn b/components/feed/core/v2/BUILD.gn
index e2d7e7e..41dfb05 100644
--- a/components/feed/core/v2/BUILD.gn
+++ b/components/feed/core/v2/BUILD.gn
@@ -80,6 +80,7 @@
     "feed_network_impl_unittest.cc",
     "feed_store_unittest.cc",
     "feed_stream_unittest.cc",
+    "metrics_reporter_unittest.cc",
     "proto_util_unittest.cc",
     "request_throttler_unittest.cc",
     "stream_model_unittest.cc",
diff --git a/components/feed/core/v2/feed_stream.cc b/components/feed/core/v2/feed_stream.cc
index 7cb98e6..691fb78 100644
--- a/components/feed/core/v2/feed_stream.cc
+++ b/components/feed/core/v2/feed_stream.cc
@@ -19,6 +19,7 @@
 #include "components/feed/core/v2/enums.h"
 #include "components/feed/core/v2/feed_network.h"
 #include "components/feed/core/v2/feed_store.h"
+#include "components/feed/core/v2/metrics_reporter.h"
 #include "components/feed/core/v2/refresh_task_scheduler.h"
 #include "components/feed/core/v2/scheduling.h"
 #include "components/feed/core/v2/stream_model.h"
@@ -203,6 +204,7 @@
 
 FeedStream::FeedStream(RefreshTaskScheduler* refresh_task_scheduler,
                        EventObserver* stream_event_observer,
+                       MetricsReporter* metrics_reporter,
                        Delegate* delegate,
                        PrefService* profile_prefs,
                        FeedNetwork* feed_network,
@@ -212,6 +214,7 @@
                        const ChromeInfo& chrome_info)
     : refresh_task_scheduler_(refresh_task_scheduler),
       stream_event_observer_(stream_event_observer),
+      metrics_reporter_(metrics_reporter),
       delegate_(delegate),
       profile_prefs_(profile_prefs),
       feed_network_(feed_network),
@@ -460,4 +463,26 @@
   model_.reset();
 }
 
+void FeedStream::ReportNavigationStarted() {
+  metrics_reporter_->NavigationStarted();
+}
+void FeedStream::ReportNavigationDone() {
+  metrics_reporter_->NavigationDone();
+}
+void FeedStream::ReportContentRemoved() {
+  metrics_reporter_->ContentRemoved();
+}
+void FeedStream::ReportNotInterestedIn() {
+  metrics_reporter_->NotInterestedIn();
+}
+void FeedStream::ReportManageInterests() {
+  metrics_reporter_->ManageInterests();
+}
+void FeedStream::ReportContextMenuOpened() {
+  metrics_reporter_->ContextMenuOpened();
+}
+void FeedStream::ReportStreamScrolled(int distance_dp) {
+  metrics_reporter_->StreamScrolled(distance_dp);
+}
+
 }  // namespace feed
diff --git a/components/feed/core/v2/feed_stream.h b/components/feed/core/v2/feed_stream.h
index fe5243c..5c9e5f3 100644
--- a/components/feed/core/v2/feed_stream.h
+++ b/components/feed/core/v2/feed_stream.h
@@ -31,10 +31,11 @@
 }  // namespace base
 
 namespace feed {
-class FeedStore;
-class StreamModel;
 class FeedNetwork;
+class FeedStore;
+class MetricsReporter;
 class RefreshTaskScheduler;
+class StreamModel;
 struct StreamModelUpdateRequest;
 
 // Implements FeedStreamApi. |FeedStream| additionally exposes functionality
@@ -77,6 +78,7 @@
 
   FeedStream(RefreshTaskScheduler* refresh_task_scheduler,
              EventObserver* stream_event_observer,
+             MetricsReporter* metrics_reporter,
              Delegate* delegate,
              PrefService* profile_prefs,
              FeedNetwork* feed_network,
@@ -105,6 +107,14 @@
   bool CommitEphemeralChange(EphemeralChangeId id) override;
   bool RejectEphemeralChange(EphemeralChangeId id) override;
 
+  void ReportNavigationStarted() override;
+  void ReportNavigationDone() override;
+  void ReportContentRemoved() override;
+  void ReportNotInterestedIn() override;
+  void ReportManageInterests() override;
+  void ReportContextMenuOpened() override;
+  void ReportStreamScrolled(int distance_dp) override;
+
   // offline_pages::TaskQueue::Delegate.
   void OnTaskQueueIsIdle() override;
 
@@ -190,6 +200,7 @@
 
   RefreshTaskScheduler* refresh_task_scheduler_;
   EventObserver* stream_event_observer_;
+  MetricsReporter* metrics_reporter_;
   Delegate* delegate_;
   PrefService* profile_prefs_;
   FeedNetwork* feed_network_;
diff --git a/components/feed/core/v2/feed_stream_unittest.cc b/components/feed/core/v2/feed_stream_unittest.cc
index 17faf11..f517a66 100644
--- a/components/feed/core/v2/feed_stream_unittest.cc
+++ b/components/feed/core/v2/feed_stream_unittest.cc
@@ -22,6 +22,7 @@
 #include "components/feed/core/proto/v2/wire/request.pb.h"
 #include "components/feed/core/shared_prefs/pref_names.h"
 #include "components/feed/core/v2/feed_network.h"
+#include "components/feed/core/v2/metrics_reporter.h"
 #include "components/feed/core/v2/refresh_task_scheduler.h"
 #include "components/feed/core/v2/scheduling.h"
 #include "components/feed/core/v2/stream_model.h"
@@ -296,9 +297,10 @@
     chrome_info.channel = version_info::Channel::STABLE;
     chrome_info.version = base::Version({99, 1, 9911, 2});
     stream_ = std::make_unique<FeedStream>(
-        &refresh_scheduler_, &event_observer_, this, &profile_prefs_, &network_,
-        store_.get(), task_environment_.GetMockClock(),
-        task_environment_.GetMockTickClock(), chrome_info);
+        &refresh_scheduler_, &event_observer_, &metrics_reporter_, this,
+        &profile_prefs_, &network_, store_.get(),
+        task_environment_.GetMockClock(), task_environment_.GetMockTickClock(),
+        chrome_info);
 
     // Set the user classifier.
     auto user_classifier = std::make_unique<TestUserClassifier>(
@@ -351,6 +353,7 @@
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
   TestUserClassifier* user_classifier_;
   TestEventObserver event_observer_;
+  MetricsReporter metrics_reporter_{task_environment_.GetMockTickClock()};
   TestingPrefServiceSimple profile_prefs_;
   TestFeedNetwork network_;
   TestWireResponseTranslator response_translator_;
diff --git a/components/feed/core/v2/metrics_reporter.cc b/components/feed/core/v2/metrics_reporter.cc
index 666aa5e2..cae4f90 100644
--- a/components/feed/core/v2/metrics_reporter.cc
+++ b/components/feed/core/v2/metrics_reporter.cc
@@ -3,10 +3,108 @@
 // found in the LICENSE file.
 #include "components/feed/core/v2/metrics_reporter.h"
 
+#include <cmath>
+
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
 
 namespace feed {
+namespace {
+using feed::internal::FeedEngagementType;
+
+void ReportEngagementTypeHistogram(FeedEngagementType engagement_type) {
+  UMA_HISTOGRAM_ENUMERATION("ContentSuggestions.Feed.EngagementType",
+                            engagement_type);
+}
+
+}  // namespace
+
+MetricsReporter::MetricsReporter(const base::TickClock* clock)
+    : clock_(clock) {}
+MetricsReporter::~MetricsReporter() = default;
+
+// Engagement Tracking.
+
+void MetricsReporter::RecordInteraction() {
+  RecordEngagement(/*scroll_distance_dp=*/0, /*interacted=*/true);
+  ReportEngagementTypeHistogram(FeedEngagementType::kFeedInteracted);
+}
+
+void MetricsReporter::RecordEngagement(int scroll_distance_dp,
+                                       bool interacted) {
+  scroll_distance_dp = std::abs(scroll_distance_dp);
+  // Determine if this interaction is part of a new 'session'.
+  auto now = clock_->NowTicks();
+  const base::TimeDelta kVisitTimeout = base::TimeDelta::FromMinutes(5);
+  if (now - visit_start_time_ > kVisitTimeout) {
+    engaged_reported_ = false;
+    engaged_simple_reported_ = false;
+  }
+  // Reset the last active time for session measurement.
+  visit_start_time_ = now;
+
+  // Report the user as engaged-simple if they have scrolled any amount or
+  // interacted with the card, and we have not already reported it for this
+  // chrome run.
+  if (!engaged_simple_reported_ && (scroll_distance_dp > 0 || interacted)) {
+    ReportEngagementTypeHistogram(FeedEngagementType::kFeedEngagedSimple);
+    engaged_simple_reported_ = true;
+  }
+
+  // Report the user as engaged if they have scrolled more than the threshold or
+  // interacted with the card, and we have not already reported it this chrome
+  // run.
+  const int kMinScrollThresholdDp = 160;  // 1 inch.
+  if (!engaged_reported_ &&
+      (scroll_distance_dp > kMinScrollThresholdDp || interacted)) {
+    ReportEngagementTypeHistogram(FeedEngagementType::kFeedEngaged);
+    engaged_reported_ = true;
+  }
+}
+
+void MetricsReporter::StreamScrolled(int distance_dp) {
+  RecordEngagement(distance_dp, /*interacted=*/false);
+
+  if (!scrolled_reported_) {
+    ReportEngagementTypeHistogram(FeedEngagementType::kFeedScrolled);
+    scrolled_reported_ = true;
+  }
+}
+
+void MetricsReporter::NavigationStarted() {
+  // TODO(harringtond): Add user actions.
+  // Report Feed_OpeningContent
+  RecordInteraction();
+}
+
+void MetricsReporter::NavigationDone() {
+  // TODO(harringtond): Use this or remove it.
+}
+
+void MetricsReporter::ContentRemoved() {
+  // TODO(harringtond): Add user actions.
+  // Report Feed_RemovedContent
+  RecordInteraction();
+}
+
+void MetricsReporter::NotInterestedIn() {
+  // TODO(harringtond): Add user actions.
+  // Report Feed_NotInterestedIn
+  RecordInteraction();
+}
+
+void MetricsReporter::ManageInterests() {
+  // TODO(harringtond): Add user actions.
+  // Report Feed_ManageInterests
+  RecordInteraction();
+}
+
+void MetricsReporter::ContextMenuOpened() {
+  // TODO(harringtond): Add user actions.
+  // Report Feed_OpenedContextMenu
+}
 
 void MetricsReporter::NetworkRequestComplete(NetworkRequestType type,
                                              int http_status_code) {
diff --git a/components/feed/core/v2/metrics_reporter.h b/components/feed/core/v2/metrics_reporter.h
index 731c059..ac7ea36 100644
--- a/components/feed/core/v2/metrics_reporter.h
+++ b/components/feed/core/v2/metrics_reporter.h
@@ -5,24 +5,71 @@
 #ifndef COMPONENTS_FEED_CORE_V2_METRICS_REPORTER_H_
 #define COMPONENTS_FEED_CORE_V2_METRICS_REPORTER_H_
 
+#include "base/time/time.h"
 #include "components/feed/core/v2/enums.h"
 #include "components/feed/core/v2/feed_stream.h"
 
+namespace base {
+class TickClock;
+}  // namespace base
+
 namespace feed {
 
+namespace internal {
+// This enum is used for a UMA histogram. Keep in sync with FeedEngagementType
+// in enums.xml.
+enum class FeedEngagementType {
+  kFeedEngaged = 0,
+  kFeedEngagedSimple = 1,
+  kFeedInteracted = 2,
+  kFeedScrolled = 3,
+  kMaxValue = FeedEngagementType::kFeedScrolled,
+};
+}  // namespace internal
+
 // Reports UMA metrics for feed.
 class MetricsReporter : public FeedStream::EventObserver {
  public:
+  explicit MetricsReporter(const base::TickClock* clock);
+  virtual ~MetricsReporter();
+  MetricsReporter(const MetricsReporter&) = delete;
+  MetricsReporter& operator=(const MetricsReporter&) = delete;
+
+  // User interactions.
+
+  void NavigationStarted();
+  void NavigationDone();
+  void ContentRemoved();
+  void NotInterestedIn();
+  void ManageInterests();
+  void ContextMenuOpened();
+  // Indicates the user scrolled the feed by |distance_dp| and then stopped
+  // scrolling.
+  void StreamScrolled(int distance_dp);
+
   // Network metrics.
+
   static void NetworkRequestComplete(NetworkRequestType type,
                                      int http_status_code);
 
   // FeedStream::EventObserver.
+
   void OnLoadStream(LoadStreamStatus load_from_store_status,
                     LoadStreamStatus final_status) override;
   void OnMaybeTriggerRefresh(TriggerType trigger,
                              bool clear_all_before_refresh) override;
   void OnClearAll(base::TimeDelta time_since_last_clear) override;
+
+ private:
+  void RecordEngagement(int scroll_distance_dp, bool interacted);
+  void RecordInteraction();
+
+  const base::TickClock* clock_;
+
+  base::TimeTicks visit_start_time_;
+  bool engaged_simple_reported_ = false;
+  bool engaged_reported_ = false;
+  bool scrolled_reported_ = false;
 };
 }  // namespace feed
 
diff --git a/components/feed/core/v2/metrics_reporter_unittest.cc b/components/feed/core/v2/metrics_reporter_unittest.cc
new file mode 100644
index 0000000..69968c00
--- /dev/null
+++ b/components/feed/core/v2/metrics_reporter_unittest.cc
@@ -0,0 +1,130 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/feed/core/v2/metrics_reporter.h"
+
+#include <map>
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace feed {
+using feed::internal::FeedEngagementType;
+const base::TimeDelta kEpsilon = base::TimeDelta::FromMilliseconds(1);
+
+class MetricsReporterTest : public testing::Test {
+ protected:
+  std::map<FeedEngagementType, int> ReportedEngagementType() {
+    std::map<FeedEngagementType, int> result;
+    for (const auto& bucket :
+         histogram_.GetAllSamples("ContentSuggestions.Feed.EngagementType")) {
+      result[static_cast<FeedEngagementType>(bucket.min)] += bucket.count;
+    }
+    return result;
+  }
+
+  base::SimpleTestTickClock clock_;
+  MetricsReporter reporter_{&clock_};
+  base::HistogramTester histogram_;
+};
+
+TEST_F(MetricsReporterTest, ScrollingSmall) {
+  reporter_.StreamScrolled(100);
+
+  std::map<FeedEngagementType, int> want({
+      {FeedEngagementType::kFeedScrolled, 1},
+      {FeedEngagementType::kFeedEngagedSimple, 1},
+  });
+  EXPECT_EQ(want, ReportedEngagementType());
+}
+
+TEST_F(MetricsReporterTest, ScrollingCanTriggerEngaged) {
+  reporter_.StreamScrolled(161);
+
+  std::map<FeedEngagementType, int> want({
+      {FeedEngagementType::kFeedScrolled, 1},
+      {FeedEngagementType::kFeedEngaged, 1},
+      {FeedEngagementType::kFeedEngagedSimple, 1},
+  });
+  EXPECT_EQ(want, ReportedEngagementType());
+}
+
+TEST_F(MetricsReporterTest, OpeningContentIsInteracting) {
+  reporter_.NavigationStarted();
+
+  std::map<FeedEngagementType, int> want({
+      {FeedEngagementType::kFeedEngaged, 1},
+      {FeedEngagementType::kFeedInteracted, 1},
+      {FeedEngagementType::kFeedEngagedSimple, 1},
+  });
+  EXPECT_EQ(want, ReportedEngagementType());
+}
+
+TEST_F(MetricsReporterTest, RemovingContentIsInteracting) {
+  reporter_.ContentRemoved();
+
+  std::map<FeedEngagementType, int> want({
+      {FeedEngagementType::kFeedEngaged, 1},
+      {FeedEngagementType::kFeedInteracted, 1},
+      {FeedEngagementType::kFeedEngagedSimple, 1},
+  });
+  EXPECT_EQ(want, ReportedEngagementType());
+}
+
+TEST_F(MetricsReporterTest, NotInterestedInIsInteracting) {
+  reporter_.NotInterestedIn();
+
+  std::map<FeedEngagementType, int> want({
+      {FeedEngagementType::kFeedEngaged, 1},
+      {FeedEngagementType::kFeedInteracted, 1},
+      {FeedEngagementType::kFeedEngagedSimple, 1},
+  });
+  EXPECT_EQ(want, ReportedEngagementType());
+}
+
+TEST_F(MetricsReporterTest, ManageInterestsInIsInteracting) {
+  reporter_.ManageInterests();
+
+  std::map<FeedEngagementType, int> want({
+      {FeedEngagementType::kFeedEngaged, 1},
+      {FeedEngagementType::kFeedInteracted, 1},
+      {FeedEngagementType::kFeedEngagedSimple, 1},
+  });
+  EXPECT_EQ(want, ReportedEngagementType());
+}
+
+TEST_F(MetricsReporterTest, VisitsCanLastMoreThanFiveMinutes) {
+  reporter_.StreamScrolled(1);
+  clock_.Advance(base::TimeDelta::FromMinutes(5) - kEpsilon);
+  reporter_.NavigationStarted();
+  clock_.Advance(base::TimeDelta::FromMinutes(5) - kEpsilon);
+  reporter_.StreamScrolled(1);
+
+  std::map<FeedEngagementType, int> want({
+      {FeedEngagementType::kFeedEngaged, 1},
+      {FeedEngagementType::kFeedInteracted, 1},
+      {FeedEngagementType::kFeedScrolled, 1},
+      {FeedEngagementType::kFeedEngagedSimple, 1},
+  });
+  EXPECT_EQ(want, ReportedEngagementType());
+}
+
+TEST_F(MetricsReporterTest, NewVisitAfterInactivity) {
+  reporter_.NavigationStarted();
+  reporter_.StreamScrolled(1);
+  clock_.Advance(base::TimeDelta::FromMinutes(5) + kEpsilon);
+  reporter_.NavigationStarted();
+  reporter_.StreamScrolled(1);
+
+  std::map<FeedEngagementType, int> want({
+      {FeedEngagementType::kFeedEngaged, 2},
+      {FeedEngagementType::kFeedInteracted, 2},
+      {FeedEngagementType::kFeedEngagedSimple, 2},
+      {FeedEngagementType::kFeedScrolled, 1},
+  });
+  EXPECT_EQ(want, ReportedEngagementType());
+}
+
+}  // namespace feed
diff --git a/components/feed/core/v2/public/feed_service.cc b/components/feed/core/v2/public/feed_service.cc
index 69723aba..13adae1 100644
--- a/components/feed/core/v2/public/feed_service.cc
+++ b/components/feed/core/v2/public/feed_service.cc
@@ -11,6 +11,7 @@
 #include "components/feed/core/v2/feed_network_impl.h"
 #include "components/feed/core/v2/feed_store.h"
 #include "components/feed/core/v2/feed_stream.h"
+#include "components/feed/core/v2/metrics_reporter.h"
 #include "components/feed/core/v2/refresh_task_scheduler.h"
 #include "net/base/network_change_notifier.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -88,17 +89,18 @@
       refresh_task_scheduler_(std::move(refresh_task_scheduler)) {
   stream_delegate_ = std::make_unique<StreamDelegateImpl>(local_state);
   network_delegate_ = std::make_unique<NetworkDelegateImpl>(delegate_.get());
+  metrics_reporter_ =
+      std::make_unique<MetricsReporter>(base::DefaultTickClock::GetInstance());
   feed_network_ = std::make_unique<FeedNetworkImpl>(
       network_delegate_.get(), identity_manager, api_key, url_loader_factory,
       base::DefaultTickClock::GetInstance(), profile_prefs);
   store_ = std::make_unique<FeedStore>(std::move(database));
 
   stream_ = std::make_unique<FeedStream>(
-      refresh_task_scheduler_.get(),
-      nullptr,  // TODO(harringtond): Implement EventObserver.
-      stream_delegate_.get(), profile_prefs, feed_network_.get(), store_.get(),
-      base::DefaultClock::GetInstance(), base::DefaultTickClock::GetInstance(),
-      chrome_info);
+      refresh_task_scheduler_.get(), metrics_reporter_.get(),
+      metrics_reporter_.get(), stream_delegate_.get(), profile_prefs,
+      feed_network_.get(), store_.get(), base::DefaultClock::GetInstance(),
+      base::DefaultTickClock::GetInstance(), chrome_info);
 
   stream_delegate_->Initialize(static_cast<FeedStream*>(stream_.get()));
 
diff --git a/components/feed/core/v2/public/feed_service.h b/components/feed/core/v2/public/feed_service.h
index d1b769e8..9051020 100644
--- a/components/feed/core/v2/public/feed_service.h
+++ b/components/feed/core/v2/public/feed_service.h
@@ -31,6 +31,7 @@
 
 namespace feed {
 class RefreshTaskScheduler;
+class MetricsReporter;
 class FeedNetwork;
 class FeedStore;
 
@@ -74,6 +75,7 @@
   // be null if |FeedStreamApi| is created externally.
   std::unique_ptr<Delegate> delegate_;
   std::unique_ptr<StreamDelegateImpl> stream_delegate_;
+  std::unique_ptr<MetricsReporter> metrics_reporter_;
   std::unique_ptr<NetworkDelegateImpl> network_delegate_;
   std::unique_ptr<FeedNetwork> feed_network_;
   std::unique_ptr<FeedStore> store_;
diff --git a/components/feed/core/v2/public/feed_stream_api.h b/components/feed/core/v2/public/feed_stream_api.h
index 0887e82..a3452c6dc 100644
--- a/components/feed/core/v2/public/feed_stream_api.h
+++ b/components/feed/core/v2/public/feed_stream_api.h
@@ -52,6 +52,16 @@
   virtual bool CommitEphemeralChange(EphemeralChangeId id) = 0;
   // Rejects a change. Returns false if the change does not exist.
   virtual bool RejectEphemeralChange(EphemeralChangeId id) = 0;
+
+  // User interaction reporting. These should have no side-effects other than
+  // reporting metrics.
+  virtual void ReportNavigationStarted() = 0;
+  virtual void ReportNavigationDone() = 0;
+  virtual void ReportContentRemoved() = 0;
+  virtual void ReportNotInterestedIn() = 0;
+  virtual void ReportManageInterests() = 0;
+  virtual void ReportContextMenuOpened() = 0;
+  virtual void ReportStreamScrolled(int distance_dp) = 0;
 };
 
 }  // namespace feed
diff --git a/components/image_fetcher/core/cache/image_cache.cc b/components/image_fetcher/core/cache/image_cache.cc
index 7fd4cd7..346811f 100644
--- a/components/image_fetcher/core/cache/image_cache.cc
+++ b/components/image_fetcher/core/cache/image_cache.cc
@@ -73,15 +73,16 @@
 
 void ImageCache::SaveImage(std::string url,
                            std::string image_data,
-                           bool needs_transcoding) {
+                           bool needs_transcoding,
+                           ExpirationInterval expiration_interval) {
   // If the image data is larger than the cache's max size, bail out.
   if (image_data.length() > kCacheMaxSize) {
     return;
   }
 
-  base::OnceClosure request =
-      base::BindOnce(&ImageCache::SaveImageImpl, weak_ptr_factory_.GetWeakPtr(),
-                     url, std::move(image_data), needs_transcoding);
+  base::OnceClosure request = base::BindOnce(
+      &ImageCache::SaveImageImpl, weak_ptr_factory_.GetWeakPtr(), url,
+      std::move(image_data), needs_transcoding, std::move(expiration_interval));
   QueueOrStartRequest(std::move(request));
 }
 
@@ -153,7 +154,8 @@
 
 void ImageCache::SaveImageImpl(const std::string& url,
                                std::string image_data,
-                               bool needs_transcoding) {
+                               bool needs_transcoding,
+                               ExpirationInterval expiration_interval) {
   std::string key = ImageCache::HashUrlToKey(url);
 
   // If the cache is full, evict some stuff.
@@ -161,7 +163,8 @@
 
   size_t length = image_data.length();
   data_store_->SaveImage(key, std::move(image_data), needs_transcoding);
-  metadata_store_->SaveImageMetadata(key, length, needs_transcoding);
+  metadata_store_->SaveImageMetadata(key, length, needs_transcoding,
+                                     std::move(expiration_interval));
 }
 
 void ImageCache::LoadImageImpl(bool read_only,
diff --git a/components/image_fetcher/core/cache/image_cache.h b/components/image_fetcher/core/cache/image_cache.h
index 577f45b05..ec19ca8 100644
--- a/components/image_fetcher/core/cache/image_cache.h
+++ b/components/image_fetcher/core/cache/image_cache.h
@@ -46,7 +46,8 @@
   // initialized yet, the call is queued.
   void SaveImage(std::string url,
                  std::string image_data,
-                 bool needs_transcoding);
+                 bool needs_transcoding,
+                 ExpirationInterval expiration_interval);
 
   // Loads the image data for the |url| and passes it to |callback|. If there's
   // no image in the cache, then an empty string is returned. If |read_only|
@@ -73,7 +74,8 @@
   // Saves the |image_data| for |url|.
   void SaveImageImpl(const std::string& url,
                      std::string image_data,
-                     bool needs_transcoding);
+                     bool needs_transcoding,
+                     ExpirationInterval expiration_interval);
   // Loads the data for |url|, calls the user back before updating metadata.
   void LoadImageImpl(bool read_only,
                      const std::string& url,
diff --git a/components/image_fetcher/core/cache/image_cache_unittest.cc b/components/image_fetcher/core/cache/image_cache_unittest.cc
index b65fedf..1b44f0b 100644
--- a/components/image_fetcher/core/cache/image_cache_unittest.cc
+++ b/components/image_fetcher/core/cache/image_cache_unittest.cc
@@ -76,7 +76,8 @@
     CreateImageCache();
     InitializeImageCache();
 
-    image_cache()->SaveImage(kImageUrl, kImageData, needs_transcoding);
+    image_cache()->SaveImage(kImageUrl, kImageData, needs_transcoding,
+                             base::nullopt /* expiration_interval */);
     RunUntilIdle();
 
     ASSERT_TRUE(IsMetadataPresent(kImageUrlHashed));
@@ -140,7 +141,8 @@
   }
 
   void InjectMetadata(std::string key, int data_size, bool needs_transcoding) {
-    metadata_store_->SaveImageMetadata(key, data_size, needs_transcoding);
+    metadata_store_->SaveImageMetadata(key, data_size, needs_transcoding,
+                                       base::nullopt /* expiration_interval */);
   }
 
   void InjectData(std::string key, std::string data, bool needs_transcoding) {
@@ -187,7 +189,8 @@
   InitializeImageCache();
 
   image_cache()->SaveImage(kImageUrl, kImageData,
-                           /* needs_transcoding */ false);
+                           /* needs_transcoding */ false,
+                           /* expiration_interval */ base::nullopt);
   RunUntilIdle();
 
   EXPECT_CALL(*this, DataCallback(false, kImageData));
@@ -215,7 +218,8 @@
 
   ASSERT_FALSE(IsCacheInitialized());
   image_cache()->SaveImage(kImageUrl, kImageData,
-                           /* needs_transcoding */ false);
+                           /* needs_transcoding */ false,
+                           /* expiration_interval */ base::nullopt);
   db()->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
   RunUntilIdle();
 
@@ -227,7 +231,8 @@
   InitializeImageCache();
 
   image_cache()->SaveImage(kImageUrl, kImageData,
-                           /* needs_transcoding */ false);
+                           /* needs_transcoding */ false,
+                           /* expiration_interval */ base::nullopt);
 
   EXPECT_CALL(*this, DataCallback(false, kImageData));
   image_cache()->LoadImage(
diff --git a/components/image_fetcher/core/cache/image_metadata_store.h b/components/image_fetcher/core/cache/image_metadata_store.h
index 3f9d88e9..5855a74 100644
--- a/components/image_fetcher/core/cache/image_metadata_store.h
+++ b/components/image_fetcher/core/cache/image_metadata_store.h
@@ -36,7 +36,8 @@
   // the existing metadata.
   virtual void SaveImageMetadata(const std::string& key,
                                  const size_t data_size,
-                                 bool needs_transcoding) = 0;
+                                 bool needs_transcoding,
+                                 ExpirationInterval expiration_interval) = 0;
 
   // Deletes the image metadata for the |key|.
   virtual void DeleteImageMetadata(const std::string& key) = 0;
diff --git a/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc b/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc
index 94ec75e..66bfaba 100644
--- a/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc
+++ b/components/image_fetcher/core/cache/image_metadata_store_leveldb.cc
@@ -105,9 +105,11 @@
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void ImageMetadataStoreLevelDB::SaveImageMetadata(const std::string& key,
-                                                  const size_t data_size,
-                                                  bool needs_transcoding) {
+void ImageMetadataStoreLevelDB::SaveImageMetadata(
+    const std::string& key,
+    const size_t data_size,
+    bool needs_transcoding,
+    ExpirationInterval expiration_interval) {
   // If the database is not initialized yet, ignore the request.
   if (!IsInitialized()) {
     return;
@@ -121,6 +123,11 @@
   metadata_proto.set_creation_time(current_time);
   metadata_proto.set_last_used_time(current_time);
   metadata_proto.set_needs_transcoding(needs_transcoding);
+  if (expiration_interval.has_value()) {
+    metadata_proto.set_cache_strategy(CacheStrategy::HOLD_UNTIL_EXPIRED);
+    metadata_proto.set_expiration_interval(
+        expiration_interval->InMicroseconds());
+  }
 
   auto entries_to_save = std::make_unique<MetadataKeyEntryVector>();
   entries_to_save->emplace_back(key, metadata_proto);
diff --git a/components/image_fetcher/core/cache/image_metadata_store_leveldb.h b/components/image_fetcher/core/cache/image_metadata_store_leveldb.h
index be7b8d7..14a2b16 100644
--- a/components/image_fetcher/core/cache/image_metadata_store_leveldb.h
+++ b/components/image_fetcher/core/cache/image_metadata_store_leveldb.h
@@ -53,7 +53,8 @@
                          ImageMetadataCallback callback) override;
   void SaveImageMetadata(const std::string& key,
                          const size_t data_size,
-                         bool needs_transcoding) override;
+                         bool needs_transcoding,
+                         ExpirationInterval expiration_interval) override;
   void DeleteImageMetadata(const std::string& key) override;
   void UpdateImageMetadata(const std::string& key) override;
   void GetAllKeys(KeysCallback callback) override;
diff --git a/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc b/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc
index e4415a1..4100975 100644
--- a/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc
+++ b/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc
@@ -64,8 +64,10 @@
   void PrepareDatabase(bool initialize) {
     CreateDatabase();
     InitializeDatabase();
-    metadata_store()->SaveImageMetadata(kImageKey, kImageDataLength,
-                                        /* needs_transcoding */ false);
+    metadata_store()->SaveImageMetadata(
+        kImageKey, kImageDataLength,
+        /* needs_transcoding */ false,
+        /* expiration_interval */ base::nullopt);
     ASSERT_TRUE(IsDataPresent(kImageKey));
 
     if (!initialize) {
@@ -101,11 +103,13 @@
     return db_store_.find(key) != db_store_.end();
   }
 
-  void AssertDataPresent(const std::string& key,
-                         int64_t data_size,
-                         base::Time creation_time,
-                         base::Time last_used_time,
-                         bool needs_transcoding) {
+  void AssertDataPresent(
+      const std::string& key,
+      int64_t data_size,
+      base::Time creation_time,
+      base::Time last_used_time,
+      bool needs_transcoding,
+      ExpirationInterval expiration_interval = base::nullopt) {
     if (!IsDataPresent(key)) {
       ASSERT_TRUE(false);
     }
@@ -117,6 +121,14 @@
     ASSERT_EQ(entry.last_used_time(),
               last_used_time.since_origin().InMicroseconds());
     ASSERT_EQ(entry.needs_transcoding(), needs_transcoding);
+    if (expiration_interval) {
+      ASSERT_EQ(entry.expiration_interval(),
+                expiration_interval->InMicroseconds());
+      ASSERT_EQ(entry.cache_strategy(), CacheStrategy::HOLD_UNTIL_EXPIRED);
+    } else {
+      ASSERT_EQ(entry.cache_strategy(), CacheStrategy::BEST_EFFORT);
+      ASSERT_FALSE(entry.has_expiration_interval());
+    }
   }
 
   void RunUntilIdle() { task_environment_.RunUntilIdle(); }
@@ -154,7 +166,8 @@
   EXPECT_FALSE(metadata_store()->IsInitialized());
   // Start an image load before the database is initialized.
   metadata_store()->SaveImageMetadata(kImageKey, kImageDataLength,
-                                      /* needs_transcoding */ false);
+                                      /* needs_transcoding */ false,
+                                      /* expiration_interval */ base::nullopt);
 
   InitializeDatabase();
   EXPECT_TRUE(metadata_store()->IsInitialized());
@@ -167,13 +180,17 @@
   InitializeDatabase();
 
   metadata_store()->SaveImageMetadata(kImageKey, kImageDataLength,
-                                      /* needs_transcoding */ false);
+                                      /* needs_transcoding */ false,
+                                      /* expiration_interval */ base::nullopt);
   AssertDataPresent(kImageKey, kImageDataLength, clock()->Now(), clock()->Now(),
                     /* needs_transcoding */ false);
+
+  ExpirationInterval expiration_interval = base::TimeDelta::FromHours(1);
   metadata_store()->SaveImageMetadata(kImageKey, kImageDataLength,
-                                      /* needs_transcoding */ true);
+                                      /* needs_transcoding */ true,
+                                      expiration_interval);
   AssertDataPresent(kImageKey, kImageDataLength, clock()->Now(), clock()->Now(),
-                    /* needs_transcoding */ true);
+                    /* needs_transcoding */ true, expiration_interval);
 }
 
 TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest, DeleteBeforeInit) {
@@ -189,7 +206,8 @@
   CreateDatabase();
   InitializeDatabase();
   metadata_store()->SaveImageMetadata(kImageKey, kImageDataLength,
-                                      /* needs_transcoding */ false);
+                                      /* needs_transcoding */ false,
+                                      /* expiration_interval */ base::nullopt);
   ASSERT_TRUE(IsDataPresent(kImageKey));
 
   // Delete the data.
@@ -204,7 +222,8 @@
   CreateDatabase();
   InitializeDatabase();
   metadata_store()->SaveImageMetadata(kImageKey, kImageDataLength,
-                                      /* needs_transcoding */ false);
+                                      /* needs_transcoding */ false,
+                                      /* expiration_interval */ base::nullopt);
   ASSERT_TRUE(IsDataPresent(kImageKey));
 
   // Delete the data.
@@ -280,7 +299,8 @@
 TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest, GetAllKeys) {
   PrepareDatabase(true);
   metadata_store()->SaveImageMetadata(kOtherImageKey, kImageDataLength,
-                                      /* needs_transcoding */ false);
+                                      /* needs_transcoding */ false,
+                                      /* expiration_interval */ base::nullopt);
 
   // A GC call before the db is initialized should be ignore.
   EXPECT_CALL(
@@ -295,7 +315,8 @@
 TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest, GetAllKeysLoadFailed) {
   PrepareDatabase(true);
   metadata_store()->SaveImageMetadata(kOtherImageKey, kImageDataLength,
-                                      /* needs_transcoding */ false);
+                                      /* needs_transcoding */ false,
+                                      /* expiration_interval */ base::nullopt);
 
   // A GC call before the db is initialized should be ignore.
   EXPECT_CALL(*this, OnKeysReturned(std::vector<std::string>({})));
@@ -366,7 +387,8 @@
   // Insert an item one our later.
   clock()->SetNow(clock()->Now() + base::TimeDelta::FromHours(1));
   metadata_store()->SaveImageMetadata(kOtherImageKey, kImageDataLength,
-                                      /* needs_transcoding */ false);
+                                      /* needs_transcoding */ false,
+                                      /* expiration_interval*/ base::nullopt);
   clock()->SetNow(clock()->Now() - base::TimeDelta::FromHours(1));
   ASSERT_TRUE(IsDataPresent(kOtherImageKey));
 
@@ -438,7 +460,8 @@
 TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest, LoadImageMetadata) {
   PrepareDatabase(true);
   metadata_store()->SaveImageMetadata(kOtherImageKey, kImageDataLength,
-                                      /* needs_transcoding */ true);
+                                      /* needs_transcoding */ true,
+                                      /* expiration_interval*/ base::nullopt);
 
   EXPECT_CALL(*this, OnImageMetadataLoaded(_));
   metadata_store()->LoadImageMetadata(
diff --git a/components/image_fetcher/core/cache/image_store_types.h b/components/image_fetcher/core/cache/image_store_types.h
index 66737a51..2e9efc0 100644
--- a/components/image_fetcher/core/cache/image_store_types.h
+++ b/components/image_fetcher/core/cache/image_store_types.h
@@ -38,6 +38,9 @@
 // Returns a vector of keys.
 using KeysCallback = base::OnceCallback<void(std::vector<std::string>)>;
 
+// The expiration interval for CacheStrategy::HOLD_UNTIL_EXPIRED.
+using ExpirationInterval = base::Optional<base::TimeDelta>;
+
 }  // namespace image_fetcher
 
 #endif  // COMPONENTS_IMAGE_FETCHER_CORE_CACHE_IMAGE_STORE_TYPES_H_
diff --git a/components/image_fetcher/core/cache/proto/cached_image_metadata.proto b/components/image_fetcher/core/cache/proto/cached_image_metadata.proto
index 407050c..0d1f965 100644
--- a/components/image_fetcher/core/cache/proto/cached_image_metadata.proto
+++ b/components/image_fetcher/core/cache/proto/cached_image_metadata.proto
@@ -8,6 +8,18 @@
 
 package image_fetcher;
 
+// Controls how cached image fetcher manages disk cache files.
+enum CacheStrategy {
+  // If reached storage space limit, the cache file may be deleted based on LRU
+  // eviction. The cache files also have a default expiration time after
+  // |creation_time|.
+  BEST_EFFORT = 0;
+
+  // The cache file will be deleted after an |expiration_interval| after
+  // |last_used_time|.
+  HOLD_UNTIL_EXPIRED = 1;
+}
+
 message CachedImageMetadataProto {
   // The key for the source image.
   optional string key = 1;
@@ -26,4 +38,11 @@
 
   // True if the image data needs transcoding before it can be trusted.
   optional bool needs_transcoding = 5;
+
+  // The cache strategy used to control the cache file lifecycle.
+  optional CacheStrategy cache_strategy = 6 [default = BEST_EFFORT];
+
+  // The expiration interval since |last_used_time| to delete the cache file for
+  // CacheStrategy::HOLD_UNTIL_EXPIRED. Measured in microseconds.
+  optional int64 expiration_interval = 7;
 }
diff --git a/components/image_fetcher/core/cached_image_fetcher.cc b/components/image_fetcher/core/cached_image_fetcher.cc
index 2c79c92..1e41467 100644
--- a/components/image_fetcher/core/cached_image_fetcher.cc
+++ b/components/image_fetcher/core/cached_image_fetcher.cc
@@ -326,7 +326,8 @@
     bool needs_transcoding = !is_image_data_transcoded &&
                              request.params.allow_needs_transcoding_file();
     image_cache_->SaveImage(std::move(url), std::move(image_data),
-                            /* needs_transcoding */ needs_transcoding);
+                            /* needs_transcoding */ needs_transcoding,
+                            request.params.expiration_interval());
   }
 }
 
diff --git a/components/image_fetcher/core/cached_image_fetcher_unittest.cc b/components/image_fetcher/core/cached_image_fetcher_unittest.cc
index 81a53879..6c52374 100644
--- a/components/image_fetcher/core/cached_image_fetcher_unittest.cc
+++ b/components/image_fetcher/core/cached_image_fetcher_unittest.cc
@@ -96,7 +96,8 @@
 
     // Use an initial request to start the cache up.
     image_cache_->SaveImage(ImageUrl().spec(), kImageData,
-                            /* needs_transcoding */ false);
+                            /* needs_transcoding */ false,
+                            /* expiration_interval */ base::nullopt);
     RunUntilIdle();
     db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
     image_cache_->DeleteImage(ImageUrl().spec());
@@ -169,7 +170,8 @@
 TEST_F(CachedImageFetcherTest, FetchImageFromCache) {
   // Save the image in the database.
   image_cache()->SaveImage(ImageUrl().spec(), kImageData,
-                           /* needs_transcoding */ false);
+                           /* needs_transcoding */ false,
+                           /* expiration_interval */ base::nullopt);
   RunUntilIdle();
 
   base::MockCallback<ImageDataFetcherCallback> data_callback;
@@ -193,7 +195,8 @@
 TEST_F(CachedImageFetcherTest, FetchImageFromCacheNeedsTranscoding) {
   // Save the image in the database.
   image_cache()->SaveImage(ImageUrl().spec(), kImageData,
-                           /* needs_transcoding */ true);
+                           /* needs_transcoding */ true,
+                           /* expiration_interval */ base::nullopt);
   RunUntilIdle();
 
   base::MockCallback<ImageDataFetcherCallback> data_callback;
@@ -219,7 +222,8 @@
   CreateCachedImageFetcher(/* read_only */ true);
   // Save the image in the database.
   image_cache()->SaveImage(ImageUrl().spec(), kImageData,
-                           /* needs_transcoding */ false);
+                           /* needs_transcoding */ false,
+                           /* expiration_interval */ base::nullopt);
   test_url_loader_factory()->AddResponse(ImageUrl().spec(), kImageData);
   RunUntilIdle();
   {
@@ -371,7 +375,8 @@
 TEST_F(CachedImageFetcherTest, FetchImageWithSkipDiskCache) {
   // Save the image in the database.
   image_cache()->SaveImage(ImageUrl().spec(), kImageDataOther,
-                           /* needs_transcoding */ false);
+                           /* needs_transcoding */ false,
+                           /* expiration_interval */ base::nullopt);
   RunUntilIdle();
   test_url_loader_factory()->AddResponse(ImageUrl().spec(), kImageData);
 
diff --git a/components/image_fetcher/core/reduced_mode_image_fetcher_unittest.cc b/components/image_fetcher/core/reduced_mode_image_fetcher_unittest.cc
index 1514ea8..6c44b28 100644
--- a/components/image_fetcher/core/reduced_mode_image_fetcher_unittest.cc
+++ b/components/image_fetcher/core/reduced_mode_image_fetcher_unittest.cc
@@ -90,7 +90,8 @@
 
     // Use an initial request to start the cache up.
     image_cache_->SaveImage(ImageUrl().spec(), kImageData,
-                            /* needs_transcoding */ false);
+                            /* needs_transcoding */ false,
+                            /* expiration_interval */ base::nullopt);
     RunUntilIdle();
     db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
     image_cache_->DeleteImage(ImageUrl().spec());
@@ -165,14 +166,16 @@
 TEST_F(ReducedModeImageFetcherTest, FetchNeedsTranscodingImageFromCache) {
   // Save the image that needs transcoding in the database.
   image_cache()->SaveImage(ImageUrl().spec(), kImageData,
-                           /* needs_transcoding */ true);
+                           /* needs_transcoding */ true,
+                           /* expiration_interval */ base::nullopt);
   VerifyCacheHit();
 }
 
 TEST_F(ReducedModeImageFetcherTest, FetchImageFromCache) {
   // Save the image that doesn't need transcoding in the database.
   image_cache()->SaveImage(ImageUrl().spec(), kImageData,
-                           /* needs_transcoding */ false);
+                           /* needs_transcoding */ false,
+                           /* expiration_interval */ base::nullopt);
   VerifyCacheHit();
 }
 
diff --git a/components/ntp_snippets/content_suggestions_service.cc b/components/ntp_snippets/content_suggestions_service.cc
index 90ca43f..71b3f56 100644
--- a/components/ntp_snippets/content_suggestions_service.cc
+++ b/components/ntp_snippets/content_suggestions_service.cc
@@ -44,12 +44,6 @@
   COUNT = 3
 };
 
-void RecordFaviconFetchResult(FaviconFetchResult result) {
-  UMA_HISTOGRAM_ENUMERATION(
-      "NewTabPage.ContentSuggestions.ArticleFaviconFetchResult", result,
-      FaviconFetchResult::COUNT);
-}
-
 }  // namespace
 
 ContentSuggestionsService::ContentSuggestionsService(
@@ -182,7 +176,6 @@
   if (!domain_with_favicon.is_valid() || !large_icon_service_) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback), gfx::Image()));
-    RecordFaviconFetchResult(FaviconFetchResult::FAILURE);
     return;
   }
 
@@ -244,11 +237,6 @@
     const favicon_base::LargeIconImageResult& result) {
   if (!result.image.IsEmpty()) {
     std::move(callback).Run(result.image);
-    // The icon is from cache if we haven't gone to Google server yet. The icon
-    // is freshly fetched, otherwise.
-    RecordFaviconFetchResult(continue_to_google_server
-                                 ? FaviconFetchResult::SUCCESS_CACHED
-                                 : FaviconFetchResult::SUCCESS_FETCHED);
     // Update the time when the icon was last requested - postpone thus the
     // automatic eviction of the favicon from the favicon database.
     large_icon_service_->TouchIconFromGoogleServer(result.icon_url);
@@ -262,7 +250,6 @@
     // cache (resulting in non-default background color) or if we already did
     // so.
     std::move(callback).Run(gfx::Image());
-    RecordFaviconFetchResult(FaviconFetchResult::FAILURE);
     return;
   }
 
@@ -308,7 +295,6 @@
     favicon_base::GoogleFaviconServerRequestStatus status) {
   if (status != favicon_base::GoogleFaviconServerRequestStatus::SUCCESS) {
     std::move(callback).Run(gfx::Image());
-    RecordFaviconFetchResult(FaviconFetchResult::FAILURE);
     return;
   }
 
diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc
index 6f7a9bf..8c5b787 100644
--- a/components/page_info/page_info.cc
+++ b/components/page_info/page_info.cc
@@ -579,13 +579,6 @@
 void PageInfo::OnChangePasswordButtonPressed(
     content::WebContents* web_contents) {
 #if BUILDFLAG(FULL_SAFE_BROWSING)
-  DCHECK(safe_browsing_status_ ==
-             SAFE_BROWSING_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE ||
-         safe_browsing_status_ ==
-             SAFE_BROWSING_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE ||
-         safe_browsing_status_ ==
-             SAFE_BROWSING_STATUS_ENTERPRISE_PASSWORD_REUSE);
-
   delegate_->OnUserActionOnPasswordUi(
       web_contents, safe_browsing::WarningAction::CHANGE_PASSWORD);
 #endif
@@ -594,13 +587,6 @@
 void PageInfo::OnWhitelistPasswordReuseButtonPressed(
     content::WebContents* web_contents) {
 #if BUILDFLAG(FULL_SAFE_BROWSING)
-  DCHECK(safe_browsing_status_ ==
-             SAFE_BROWSING_STATUS_SIGNED_IN_SYNC_PASSWORD_REUSE ||
-         safe_browsing_status_ ==
-             SAFE_BROWSING_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE ||
-         safe_browsing_status_ ==
-             SAFE_BROWSING_STATUS_ENTERPRISE_PASSWORD_REUSE);
-
   delegate_->OnUserActionOnPasswordUi(
       web_contents, safe_browsing::WarningAction::MARK_AS_LEGITIMATE);
 #endif
@@ -756,7 +742,9 @@
                  MALICIOUS_CONTENT_STATUS_SIGNED_IN_NON_SYNC_PASSWORD_REUSE ||
          visible_security_state.malicious_content_status ==
              security_state::
-                 MALICIOUS_CONTENT_STATUS_ENTERPRISE_PASSWORD_REUSE);
+                 MALICIOUS_CONTENT_STATUS_ENTERPRISE_PASSWORD_REUSE ||
+         visible_security_state.malicious_content_status ==
+             security_state::MALICIOUS_CONTENT_STATUS_SAVED_PASSWORD_REUSE);
 #if BUILDFLAG(FULL_SAFE_BROWSING)
     // Only record password reuse when adding the button, not on updates.
     if (show_change_password_buttons_ && !old_show_change_pw_buttons) {
diff --git a/components/performance_manager/BUILD.gn b/components/performance_manager/BUILD.gn
index e248ba7..7ff448f6 100644
--- a/components/performance_manager/BUILD.gn
+++ b/components/performance_manager/BUILD.gn
@@ -81,8 +81,10 @@
     "public/graph/worker_node.h",
     "public/performance_manager.h",
     "public/performance_manager_main_thread_observer.h",
+    "public/render_frame_host_proxy.h",
     "public/render_process_host_proxy.h",
     "public/web_contents_proxy.h",
+    "render_frame_host_proxy.cc",
     "render_process_host_proxy.cc",
     "render_process_user_data.cc",
     "render_process_user_data.h",
diff --git a/components/performance_manager/graph/frame_node_impl.cc b/components/performance_manager/graph/frame_node_impl.cc
index 69d916c..6eb3db5 100644
--- a/components/performance_manager/graph/frame_node_impl.cc
+++ b/components/performance_manager/graph/frame_node_impl.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/bind.h"
 #include "components/performance_manager/graph/graph_impl.h"
 #include "components/performance_manager/graph/page_node_impl.h"
 #include "components/performance_manager/graph/process_node_impl.h"
@@ -35,7 +36,11 @@
       render_frame_id_(render_frame_id),
       dev_tools_token_(dev_tools_token),
       browsing_instance_id_(browsing_instance_id),
-      site_instance_id_(site_instance_id) {
+      site_instance_id_(site_instance_id),
+      render_frame_host_proxy_(content::GlobalFrameRoutingId(
+          process_node->render_process_host_proxy().render_process_host_id(),
+          render_frame_id)),
+      weak_factory_(this) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
   DCHECK(process_node);
   DCHECK(page_node);
@@ -93,6 +98,11 @@
   document_.had_form_interaction.SetAndMaybeNotify(this, true);
 }
 
+const RenderFrameHostProxy& FrameNodeImpl::GetRenderFrameHostProxy() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return render_frame_host_proxy();
+}
+
 bool FrameNodeImpl::IsMainFrame() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return !parent_frame_node_;
@@ -130,6 +140,10 @@
   return site_instance_id_;
 }
 
+const RenderFrameHostProxy& FrameNodeImpl::render_frame_host_proxy() const {
+  return render_frame_host_proxy_;
+}
+
 const base::flat_set<FrameNodeImpl*>& FrameNodeImpl::child_frame_nodes() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return child_frame_nodes_;
@@ -323,6 +337,17 @@
   return site_instance_id();
 }
 
+bool FrameNodeImpl::VisitChildFrameNodes(
+    const FrameNodeVisitor& visitor) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  for (auto* frame_impl : child_frame_nodes()) {
+    const FrameNode* frame = frame_impl;
+    if (!visitor.Run(frame))
+      return false;
+  }
+  return true;
+}
+
 const base::flat_set<const FrameNode*> FrameNodeImpl::GetChildFrameNodes()
     const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/components/performance_manager/graph/frame_node_impl.h b/components/performance_manager/graph/frame_node_impl.h
index e996870..2ac334d 100644
--- a/components/performance_manager/graph/frame_node_impl.h
+++ b/components/performance_manager/graph/frame_node_impl.h
@@ -9,9 +9,11 @@
 
 #include "base/containers/flat_set.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "base/unguessable_token.h"
 #include "components/performance_manager/graph/node_base.h"
 #include "components/performance_manager/public/graph/frame_node.h"
+#include "components/performance_manager/public/render_frame_host_proxy.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "url/gurl.h"
@@ -77,8 +79,9 @@
   void SetIsAdFrame() override;
   void OnNonPersistentNotificationCreated() override;
   void SetHadFormInteraction() override;
+  const RenderFrameHostProxy& GetRenderFrameHostProxy() const override;
 
-  // Partial FrameNode implementation:
+  // Partial FrameNodbase::TimeDelta time_since_navigatione implementation:
   bool IsMainFrame() const override;
 
   // Getters for const properties. These can be called from any thread.
@@ -90,6 +93,7 @@
   const base::UnguessableToken& dev_tools_token() const;
   int32_t browsing_instance_id() const;
   int32_t site_instance_id() const;
+  const RenderFrameHostProxy& render_frame_host_proxy() const;
 
   // Getters for non-const properties. These are not thread safe.
   const base::flat_set<FrameNodeImpl*>& child_frame_nodes() const;
@@ -121,6 +125,10 @@
   // Invoked to set the frame priority, and the reason behind it.
   void SetPriorityAndReason(const PriorityAndReason& priority_and_reason);
 
+  base::WeakPtr<FrameNodeImpl> GetWeakPtr() {
+    return weak_factory_.GetWeakPtr();
+  }
+
  private:
   friend class FramePriorityAccess;
   friend class PageNodeImpl;
@@ -135,6 +143,7 @@
   const base::UnguessableToken& GetDevToolsToken() const override;
   int32_t GetBrowsingInstanceId() const override;
   int32_t GetSiteInstanceId() const override;
+  bool VisitChildFrameNodes(const FrameNodeVisitor& visitor) const override;
   const base::flat_set<const FrameNode*> GetChildFrameNodes() const override;
   LifecycleState GetLifecycleState() const override;
   InterventionPolicy GetOriginTrialFreezePolicy() const override;
@@ -220,6 +229,9 @@
   // same SiteInstance may sychronously script each other. Frames with the
   // same |site_instance_id_| will also have the same |browsing_instance_id_|.
   const int32_t site_instance_id_;
+  // A proxy object that lets the underlying RFH be safely dereferenced on the
+  // UI thread.
+  const RenderFrameHostProxy render_frame_host_proxy_;
 
   base::flat_set<FrameNodeImpl*> child_frame_nodes_;
 
@@ -271,6 +283,8 @@
   // Inline storage for FramePriorityDecorator data.
   frame_priority::AcceptedVote accepted_vote_;
 
+  base::WeakPtrFactory<FrameNodeImpl> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(FrameNodeImpl);
 };
 
diff --git a/components/performance_manager/graph/frame_node_impl_unittest.cc b/components/performance_manager/graph/frame_node_impl_unittest.cc
index 8b95b28..4c1c0d3 100644
--- a/components/performance_manager/graph/frame_node_impl_unittest.cc
+++ b/components/performance_manager/graph/frame_node_impl_unittest.cc
@@ -17,6 +17,10 @@
 
 using FrameNodeImplTest = GraphTestHarness;
 
+const FrameNode* ToPublic(FrameNodeImpl* frame_node) {
+  return frame_node;
+}
+
 }  // namespace
 
 TEST_F(FrameNodeImplTest, SafeDowncast) {
@@ -384,4 +388,36 @@
             public_frame_node->HadFormInteraction());
 }
 
+TEST_F(FrameNodeImplTest, VisitChildFrameNodes) {
+  auto process = CreateNode<ProcessNodeImpl>();
+  auto page = CreateNode<PageNodeImpl>();
+  auto frame1 = CreateFrameNodeAutoId(process.get(), page.get());
+  auto frame2 = CreateFrameNodeAutoId(process.get(), page.get(), frame1.get());
+  auto frame3 = CreateFrameNodeAutoId(process.get(), page.get(), frame1.get());
+
+  std::set<const FrameNode*> visited;
+  EXPECT_TRUE(
+      ToPublic(frame1.get())
+          ->VisitChildFrameNodes(base::BindRepeating(
+              [](std::set<const FrameNode*>* visited, const FrameNode* frame) {
+                EXPECT_TRUE(visited->insert(frame).second);
+                return true;
+              },
+              base::Unretained(&visited))));
+  EXPECT_THAT(visited, testing::UnorderedElementsAre(ToPublic(frame2.get()),
+                                                     ToPublic(frame3.get())));
+
+  // Do an aborted visit.
+  visited.clear();
+  EXPECT_FALSE(
+      ToPublic(frame1.get())
+          ->VisitChildFrameNodes(base::BindRepeating(
+              [](std::set<const FrameNode*>* visited, const FrameNode* frame) {
+                EXPECT_TRUE(visited->insert(frame).second);
+                return false;
+              },
+              base::Unretained(&visited))));
+  EXPECT_EQ(1u, visited.size());
+}
+
 }  // namespace performance_manager
diff --git a/components/performance_manager/graph/graph_impl_operations.h b/components/performance_manager/graph/graph_impl_operations.h
index 5b60865..c7807f7b 100644
--- a/components/performance_manager/graph/graph_impl_operations.h
+++ b/components/performance_manager/graph/graph_impl_operations.h
@@ -37,12 +37,13 @@
   // Traverse the frame tree of a |page| in the given order, invoking the
   // provided |callable| for each frame node in the tree. The |callable| has to
   // provide a "bool operator()(FrameNodeImpl*)". If the visitor returns false
-  // then the iteration is halted.
+  // then the iteration is halted. Returns true if all calls to the visitor
+  // returned true, false otherwise.
   template <typename Callable>
-  static void VisitFrameTreePreOrder(const PageNodeImpl* page,
+  static bool VisitFrameTreePreOrder(const PageNodeImpl* page,
                                      Callable callable);
   template <typename Callable>
-  static void VisitFrameTreePostOrder(const PageNodeImpl* page,
+  static bool VisitFrameTreePostOrder(const PageNodeImpl* page,
                                       Callable callable);
 
   // Returns true if the given |frame| is in the frame tree associated with the
@@ -69,29 +70,30 @@
 }
 
 template <typename Callable>
-void VisitFrameTree(const PageNodeImpl* page,
+bool VisitFrameTree(const PageNodeImpl* page,
                     Callable callable,
                     bool pre_order) {
   for (auto* main_frame_node : page->main_frame_nodes()) {
     if (!VisitFrameAndChildren(main_frame_node, callable, pre_order))
-      return;
+      return false;
   }
+  return true;
 }
 
 }  // namespace internal
 
 // static
 template <typename Callable>
-void GraphImplOperations::VisitFrameTreePreOrder(const PageNodeImpl* page,
+bool GraphImplOperations::VisitFrameTreePreOrder(const PageNodeImpl* page,
                                                  Callable callable) {
-  internal::VisitFrameTree(page, callable, true);
+  return internal::VisitFrameTree(page, callable, true);
 }
 
 // static
 template <typename Callable>
-void GraphImplOperations::VisitFrameTreePostOrder(const PageNodeImpl* page,
+bool GraphImplOperations::VisitFrameTreePostOrder(const PageNodeImpl* page,
                                                   Callable callable) {
-  internal::VisitFrameTree(page, callable, false);
+  return internal::VisitFrameTree(page, callable, false);
 }
 
 }  // namespace performance_manager
diff --git a/components/performance_manager/graph/graph_impl_operations_unittest.cc b/components/performance_manager/graph/graph_impl_operations_unittest.cc
index 7701f1e..c518de2 100644
--- a/components/performance_manager/graph/graph_impl_operations_unittest.cc
+++ b/components/performance_manager/graph/graph_impl_operations_unittest.cc
@@ -93,28 +93,46 @@
   auto frame_nodes = GraphImplOperations::GetFrameNodes(page1_.get());
 
   std::vector<FrameNodeImpl*> visited;
-  GraphImplOperations::VisitFrameTreePreOrder(
+  EXPECT_TRUE(GraphImplOperations::VisitFrameTreePreOrder(
       page1_.get(), [&visited](FrameNodeImpl* frame_node) -> bool {
         visited.push_back(frame_node);
         return true;
-      });
+      }));
   EXPECT_THAT(visited,
               testing::UnorderedElementsAre(
                   mainframe1_.get(), childframe1a_.get(), childframe1b_.get()));
   // In pre-order the main frame is first.
   EXPECT_EQ(mainframe1_.get(), visited[0]);
 
+  // Do an aborted visit pre-order visit.
   visited.clear();
-  GraphImplOperations::VisitFrameTreePostOrder(
+  EXPECT_FALSE(GraphImplOperations::VisitFrameTreePreOrder(
+      page1_.get(), [&visited](FrameNodeImpl* frame_node) -> bool {
+        visited.push_back(frame_node);
+        return false;
+      }));
+  EXPECT_EQ(1u, visited.size());
+
+  visited.clear();
+  EXPECT_TRUE(GraphImplOperations::VisitFrameTreePostOrder(
       page1_.get(), [&visited](FrameNodeImpl* frame_node) -> bool {
         visited.push_back(frame_node);
         return true;
-      });
+      }));
   EXPECT_THAT(visited,
               testing::UnorderedElementsAre(
                   mainframe1_.get(), childframe1a_.get(), childframe1b_.get()));
   // In post-order the main frame is last.
   EXPECT_EQ(mainframe1_.get(), visited[2]);
+
+  // Do an aborted post-order visit.
+  visited.clear();
+  EXPECT_FALSE(GraphImplOperations::VisitFrameTreePostOrder(
+      page1_.get(), [&visited](FrameNodeImpl* frame_node) -> bool {
+        visited.push_back(frame_node);
+        return false;
+      }));
+  EXPECT_EQ(1u, visited.size());
 }
 
 TEST_F(GraphImplOperationsTest, HasFrame) {
diff --git a/components/performance_manager/graph/graph_operations.cc b/components/performance_manager/graph/graph_operations.cc
index 1151a1f..07ec5586 100644
--- a/components/performance_manager/graph/graph_operations.cc
+++ b/components/performance_manager/graph/graph_operations.cc
@@ -55,9 +55,9 @@
 }
 
 // static
-void GraphOperations::VisitFrameTreePreOrder(const PageNode* page,
+bool GraphOperations::VisitFrameTreePreOrder(const PageNode* page,
                                              const FrameNodeVisitor& visitor) {
-  GraphImplOperations::VisitFrameTreePreOrder(
+  return GraphImplOperations::VisitFrameTreePreOrder(
       PageNodeImpl::FromNode(page),
       [&visitor](FrameNodeImpl* frame_impl) -> bool {
         const FrameNode* frame = frame_impl;
@@ -66,9 +66,9 @@
 }
 
 // static
-void GraphOperations::VisitFrameTreePostOrder(const PageNode* page,
+bool GraphOperations::VisitFrameTreePostOrder(const PageNode* page,
                                               const FrameNodeVisitor& visitor) {
-  GraphImplOperations::VisitFrameTreePostOrder(
+  return GraphImplOperations::VisitFrameTreePostOrder(
       PageNodeImpl::FromNode(page),
       [&visitor](FrameNodeImpl* frame_impl) -> bool {
         const FrameNode* frame = frame_impl;
diff --git a/components/performance_manager/graph/graph_operations_unittest.cc b/components/performance_manager/graph/graph_operations_unittest.cc
index a85df28..463bd32 100644
--- a/components/performance_manager/graph/graph_operations_unittest.cc
+++ b/components/performance_manager/graph/graph_operations_unittest.cc
@@ -99,14 +99,14 @@
   auto frame_nodes = GraphOperations::GetFrameNodes(page1_.get());
 
   std::vector<const FrameNode*> visited;
-  GraphOperations::VisitFrameTreePreOrder(
+  EXPECT_TRUE(GraphOperations::VisitFrameTreePreOrder(
       page1_.get(), base::BindRepeating(
                         [](std::vector<const FrameNode*>* visited,
                            const FrameNode* frame_node) -> bool {
                           visited->push_back(frame_node);
                           return true;
                         },
-                        base::Unretained(&visited)));
+                        base::Unretained(&visited))));
   EXPECT_THAT(visited,
               testing::UnorderedElementsAre(ToPublic(mainframe1_.get()),
                                             ToPublic(childframe1a_.get()),
@@ -114,21 +114,45 @@
   // In pre-order the main frame is first.
   EXPECT_EQ(ToPublic(mainframe1_.get()), visited[0]);
 
+  // Do an aborted pre-order visit.
   visited.clear();
-  GraphOperations::VisitFrameTreePostOrder(
+  EXPECT_FALSE(GraphOperations::VisitFrameTreePreOrder(
+      page1_.get(), base::BindRepeating(
+                        [](std::vector<const FrameNode*>* visited,
+                           const FrameNode* frame_node) -> bool {
+                          visited->push_back(frame_node);
+                          return false;
+                        },
+                        base::Unretained(&visited))));
+  EXPECT_EQ(1u, visited.size());
+
+  visited.clear();
+  EXPECT_TRUE(GraphOperations::VisitFrameTreePostOrder(
       page1_.get(), base::BindRepeating(
                         [](std::vector<const FrameNode*>* visited,
                            const FrameNode* frame_node) -> bool {
                           visited->push_back(frame_node);
                           return true;
                         },
-                        base::Unretained(&visited)));
+                        base::Unretained(&visited))));
   EXPECT_THAT(visited,
               testing::UnorderedElementsAre(ToPublic(mainframe1_.get()),
                                             ToPublic(childframe1a_.get()),
                                             ToPublic(childframe1b_.get())));
   // In post-order the main frame is last.
   EXPECT_EQ(mainframe1_.get(), visited[2]);
+
+  // Do an aborted post-order visit.
+  visited.clear();
+  EXPECT_FALSE(GraphOperations::VisitFrameTreePostOrder(
+      page1_.get(), base::BindRepeating(
+                        [](std::vector<const FrameNode*>* visited,
+                           const FrameNode* frame_node) -> bool {
+                          visited->push_back(frame_node);
+                          return false;
+                        },
+                        base::Unretained(&visited))));
+  EXPECT_EQ(1u, visited.size());
 }
 
 TEST_F(GraphOperationsTest, HasFrame) {
diff --git a/components/performance_manager/graph/page_node_impl.cc b/components/performance_manager/graph/page_node_impl.cc
index 6ee39cf1..2b4bca18 100644
--- a/components/performance_manager/graph/page_node_impl.cc
+++ b/components/performance_manager/graph/page_node_impl.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/bind.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "base/time/default_tick_clock.h"
@@ -334,6 +335,16 @@
   return GetMainFrameNodeImpl();
 }
 
+bool PageNodeImpl::VisitMainFrameNodes(const FrameNodeVisitor& visitor) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  for (auto* frame_impl : main_frame_nodes_) {
+    const FrameNode* frame = frame_impl;
+    if (!visitor.Run(frame))
+      return false;
+  }
+  return true;
+}
+
 const base::flat_set<const FrameNode*> PageNodeImpl::GetMainFrameNodes() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   base::flat_set<const FrameNode*> main_frame_nodes(main_frame_nodes_.begin(),
diff --git a/components/performance_manager/graph/page_node_impl.h b/components/performance_manager/graph/page_node_impl.h
index 50694c72..1358b73 100644
--- a/components/performance_manager/graph/page_node_impl.h
+++ b/components/performance_manager/graph/page_node_impl.h
@@ -128,6 +128,7 @@
   const std::string& GetContentsMimeType() const override;
   base::TimeDelta GetTimeSinceLastNavigation() const override;
   const FrameNode* GetMainFrameNode() const override;
+  bool VisitMainFrameNodes(const FrameNodeVisitor& visitor) const override;
   const base::flat_set<const FrameNode*> GetMainFrameNodes() const override;
   const GURL& GetMainFrameUrl() const override;
   bool HadFormInteraction() const override;
diff --git a/components/performance_manager/graph/page_node_impl_unittest.cc b/components/performance_manager/graph/page_node_impl_unittest.cc
index 25f6c42..6283d5f 100644
--- a/components/performance_manager/graph/page_node_impl_unittest.cc
+++ b/components/performance_manager/graph/page_node_impl_unittest.cc
@@ -23,6 +23,14 @@
 const std::string kHtmlMimeType = "text/html";
 const std::string kPdfMimeType = "application/pdf";
 
+const PageNode* ToPublic(PageNodeImpl* page_node) {
+  return page_node;
+}
+
+const FrameNode* ToPublic(FrameNodeImpl* frame_node) {
+  return frame_node;
+}
+
 }  // namespace
 
 TEST_F(PageNodeImplTest, SafeDowncast) {
@@ -325,4 +333,46 @@
             public_page_node->GetContentsMimeType());
 }
 
+TEST_F(PageNodeImplTest, GetMainFrameNodes) {
+  auto process = CreateNode<ProcessNodeImpl>();
+  auto page = CreateNode<PageNodeImpl>();
+  auto frame1 = CreateFrameNodeAutoId(process.get(), page.get());
+  auto frame2 = CreateFrameNodeAutoId(process.get(), page.get());
+
+  auto frames = ToPublic(page.get())->GetMainFrameNodes();
+  EXPECT_THAT(frames, testing::UnorderedElementsAre(ToPublic(frame1.get()),
+                                                    ToPublic(frame2.get())));
+}
+
+TEST_F(PageNodeImplTest, VisitMainFrameNodes) {
+  auto process = CreateNode<ProcessNodeImpl>();
+  auto page = CreateNode<PageNodeImpl>();
+  auto frame1 = CreateFrameNodeAutoId(process.get(), page.get());
+  auto frame2 = CreateFrameNodeAutoId(process.get(), page.get());
+
+  std::set<const FrameNode*> visited;
+  EXPECT_TRUE(
+      ToPublic(page.get())
+          ->VisitMainFrameNodes(base::BindRepeating(
+              [](std::set<const FrameNode*>* visited, const FrameNode* frame) {
+                EXPECT_TRUE(visited->insert(frame).second);
+                return true;
+              },
+              base::Unretained(&visited))));
+  EXPECT_THAT(visited, testing::UnorderedElementsAre(ToPublic(frame1.get()),
+                                                     ToPublic(frame2.get())));
+
+  // Do an aborted visit.
+  visited.clear();
+  EXPECT_FALSE(
+      ToPublic(page.get())
+          ->VisitMainFrameNodes(base::BindRepeating(
+              [](std::set<const FrameNode*>* visited, const FrameNode* frame) {
+                EXPECT_TRUE(visited->insert(frame).second);
+                return false;
+              },
+              base::Unretained(&visited))));
+  EXPECT_EQ(1u, visited.size());
+}
+
 }  // namespace performance_manager
diff --git a/components/performance_manager/graph/process_node_impl.cc b/components/performance_manager/graph/process_node_impl.cc
index 0a6bafa..8bceef0 100644
--- a/components/performance_manager/graph/process_node_impl.cc
+++ b/components/performance_manager/graph/process_node_impl.cc
@@ -162,13 +162,14 @@
   return exit_status();
 }
 
-void ProcessNodeImpl::VisitFrameNodes(const FrameNodeVisitor& visitor) const {
+bool ProcessNodeImpl::VisitFrameNodes(const FrameNodeVisitor& visitor) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto* frame_impl : frame_nodes()) {
     const FrameNode* frame = frame_impl;
     if (!visitor.Run(frame))
-      return;
+      return false;
   }
+  return true;
 }
 
 base::flat_set<const FrameNode*> ProcessNodeImpl::GetFrameNodes() const {
diff --git a/components/performance_manager/graph/process_node_impl.h b/components/performance_manager/graph/process_node_impl.h
index fca92434..0344530 100644
--- a/components/performance_manager/graph/process_node_impl.h
+++ b/components/performance_manager/graph/process_node_impl.h
@@ -132,7 +132,7 @@
   const base::Process& GetProcess() const override;
   base::Time GetLaunchTime() const override;
   base::Optional<int32_t> GetExitStatus() const override;
-  void VisitFrameNodes(const FrameNodeVisitor& visitor) const override;
+  bool VisitFrameNodes(const FrameNodeVisitor& visitor) const override;
   base::flat_set<const FrameNode*> GetFrameNodes() const override;
   base::TimeDelta GetExpectedTaskQueueingDuration() const override;
   bool GetMainThreadTaskLoadIsLow() const override;
diff --git a/components/performance_manager/public/graph/frame_node.h b/components/performance_manager/public/graph/frame_node.h
index c1175c7c..d3d49d9 100644
--- a/components/performance_manager/public/graph/frame_node.h
+++ b/components/performance_manager/public/graph/frame_node.h
@@ -23,6 +23,7 @@
 class FrameNodeObserver;
 class PageNode;
 class ProcessNode;
+class RenderFrameHostProxy;
 class WorkerNode;
 
 // Frame nodes form a tree structure, each FrameNode at most has one parent that
@@ -52,8 +53,9 @@
 // it.
 class FrameNode : public Node {
  public:
-  using LifecycleState = mojom::LifecycleState;
+  using FrameNodeVisitor = base::RepeatingCallback<bool(const FrameNode*)>;
   using InterventionPolicy = mojom::InterventionPolicy;
+  using LifecycleState = mojom::LifecycleState;
   using Observer = FrameNodeObserver;
   using PriorityAndReason = frame_priority::PriorityAndReason;
 
@@ -98,9 +100,14 @@
   // called from any thread.
   virtual bool IsMainFrame() const = 0;
 
+  // Visits the frame nodes that are children of this frame. The iteration is
+  // halted if the visitor returns false. Returns true if every call to the
+  // visitor returned true, false otherwise.
+  virtual bool VisitChildFrameNodes(const FrameNodeVisitor& visitor) const = 0;
+
   // Returns the set of child frame associated with this frame. Note that this
-  // incurs a full container copy of all child nodes. Please use ForEach when
-  // that makes sense.
+  // incurs a full container copy of all child nodes. Please use
+  // VisitChildFrameNodes when that makes sense.
   virtual const base::flat_set<const FrameNode*> GetChildFrameNodes() const = 0;
 
   // Returns the current lifecycle state of this frame. See
@@ -153,6 +160,10 @@
   // Returns true if at least one form of the frame has been interacted with.
   virtual bool HadFormInteraction() const = 0;
 
+  // Returns a proxy to the RenderFrameHost associated with this node. The
+  // proxy may only be dereferenced on the UI thread.
+  virtual const RenderFrameHostProxy& GetRenderFrameHostProxy() const = 0;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(FrameNode);
 };
@@ -246,12 +257,12 @@
   void OnFrameIsHoldingWebLockChanged(const FrameNode* frame_node) override {}
   void OnFrameIsHoldingIndexedDBLockChanged(
       const FrameNode* frame_node) override {}
-  void OnNonPersistentNotificationCreated(
-      const FrameNode* frame_node) override {}
   void OnPriorityAndReasonChanged(
       const FrameNode* frame_node,
       const PriorityAndReason& previous_value) override {}
   void OnHadFormInteractionChanged(const FrameNode* frame_node) override {}
+  void OnNonPersistentNotificationCreated(
+      const FrameNode* frame_node) override {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ObserverDefaultImpl);
diff --git a/components/performance_manager/public/graph/graph_operations.h b/components/performance_manager/public/graph/graph_operations.h
index a3776fd..9e2c55c 100644
--- a/components/performance_manager/public/graph/graph_operations.h
+++ b/components/performance_manager/public/graph/graph_operations.h
@@ -38,10 +38,11 @@
 
   // Traverse the frame tree of a |page| in the given order, invoking the
   // provided |callable| for each frame node in the tree. If the visitor returns
-  // false then then the iteration is halted.
-  static void VisitFrameTreePreOrder(const PageNode* page,
+  // false then then the iteration is halted. Returns true if all calls to the
+  // visitor returned true, false otherwise.
+  static bool VisitFrameTreePreOrder(const PageNode* page,
                                      const FrameNodeVisitor& visitor);
-  static void VisitFrameTreePostOrder(const PageNode* page,
+  static bool VisitFrameTreePostOrder(const PageNode* page,
                                       const FrameNodeVisitor& visitor);
 
   // Returns true if the given |frame| is in the frame tree associated with the
diff --git a/components/performance_manager/public/graph/page_node.h b/components/performance_manager/public/graph/page_node.h
index de1e13f..d02c6ed6 100644
--- a/components/performance_manager/public/graph/page_node.h
+++ b/components/performance_manager/public/graph/page_node.h
@@ -27,6 +27,7 @@
 // Extensions.
 class PageNode : public Node {
  public:
+  using FrameNodeVisitor = base::RepeatingCallback<bool(const FrameNode*)>;
   using InterventionPolicy = mojom::InterventionPolicy;
   using LifecycleState = mojom::LifecycleState;
   using Observer = PageNodeObserver;
@@ -97,8 +98,15 @@
   // are no main frames at the moment, returns nullptr.
   virtual const FrameNode* GetMainFrameNode() const = 0;
 
+  // Visits the main frame nodes associated with this page. The iteration is
+  // halted if the visitor returns false. Returns true if every call to the
+  // visitor returned true, false otherwise.
+  virtual bool VisitMainFrameNodes(const FrameNodeVisitor& visitor) const = 0;
+
   // Returns all of the main frame nodes, both current and otherwise. If there
-  // are no main frames at the moment, returns the empty set.
+  // are no main frames at the moment, returns the empty set. Note that this
+  // incurs a full container copy of all main frame nodes. Please use
+  // VisitMainFrameNodes when that makes sense.
   virtual const base::flat_set<const FrameNode*> GetMainFrameNodes() const = 0;
 
   // Returns the URL the main frame last committed a navigation to, or the
diff --git a/components/performance_manager/public/graph/process_node.h b/components/performance_manager/public/graph/process_node.h
index 912375f7..2893296 100644
--- a/components/performance_manager/public/graph/process_node.h
+++ b/components/performance_manager/public/graph/process_node.h
@@ -66,8 +66,9 @@
   virtual base::Optional<int32_t> GetExitStatus() const = 0;
 
   // Visits the frame nodes that are hosted in this process. The iteration is
-  // halted if the visitor returns false.
-  virtual void VisitFrameNodes(const FrameNodeVisitor& visitor) const = 0;
+  // halted if the visitor returns false. Returns true if every call to the
+  // visitor returned true, false otherwise.
+  virtual bool VisitFrameNodes(const FrameNodeVisitor& visitor) const = 0;
 
   // Returns the set of frame nodes that are hosted in this process. Note that
   // calling this causes the set of nodes to be generated.
diff --git a/components/performance_manager/public/render_frame_host_proxy.h b/components/performance_manager/public/render_frame_host_proxy.h
new file mode 100644
index 0000000..30815c38
--- /dev/null
+++ b/components/performance_manager/public/render_frame_host_proxy.h
@@ -0,0 +1,52 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_RENDER_FRAME_HOST_PROXY_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_RENDER_FRAME_HOST_PROXY_H_
+
+#include "content/public/browser/global_routing_id.h"
+
+namespace content {
+class RenderFrameHost;
+}  // namespace content
+
+namespace performance_manager {
+
+class FrameNodeImpl;
+
+// A RenderFrameHostProxy is used to post messages out of the performance
+// manager sequence that are bound for a RenderFrameHostProxy running on the UI
+// thread. The object is bound to the UI thread. A RenderFrameHostProxy is
+// conceptually equivalent to a WeakPtr<RenderProcessHost>. Copy and assignment
+// are explicitly allowed for this object.
+class RenderFrameHostProxy {
+ public:
+  RenderFrameHostProxy();
+  RenderFrameHostProxy(const RenderFrameHostProxy& other);
+  ~RenderFrameHostProxy();
+  RenderFrameHostProxy& operator=(const RenderFrameHostProxy& other);
+
+  // Allows resolving this proxy to the underlying RenderFrameHost. This must
+  // only be called on the UI thread. Returns nullptr if the RenderFrameHost
+  // no longer exists.
+  content::RenderFrameHost* Get() const;
+
+  // Returns the global routing ID.
+  const content::GlobalFrameRoutingId& global_frame_routing_id() const {
+    return global_frame_routing_id_;
+  }
+
+ protected:
+  friend class FrameNodeImpl;
+
+  explicit RenderFrameHostProxy(
+      const content::GlobalFrameRoutingId& global_frame_routing_id);
+
+ private:
+  content::GlobalFrameRoutingId global_frame_routing_id_;
+};
+
+}  // namespace performance_manager
+
+#endif  // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_RENDER_FRAME_HOST_PROXY_H_
diff --git a/components/performance_manager/render_frame_host_proxy.cc b/components/performance_manager/render_frame_host_proxy.cc
new file mode 100644
index 0000000..0fb0596
--- /dev/null
+++ b/components/performance_manager/render_frame_host_proxy.cc
@@ -0,0 +1,26 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/performance_manager/public/render_frame_host_proxy.h"
+
+#include "content/public/browser/render_frame_host.h"
+
+namespace performance_manager {
+
+RenderFrameHostProxy::RenderFrameHostProxy() = default;
+RenderFrameHostProxy::~RenderFrameHostProxy() = default;
+RenderFrameHostProxy::RenderFrameHostProxy(const RenderFrameHostProxy& other) =
+    default;
+RenderFrameHostProxy& RenderFrameHostProxy::operator=(
+    const RenderFrameHostProxy& other) = default;
+
+content::RenderFrameHost* RenderFrameHostProxy::Get() const {
+  return content::RenderFrameHost::FromID(global_frame_routing_id_);
+}
+
+RenderFrameHostProxy::RenderFrameHostProxy(
+    const content::GlobalFrameRoutingId& global_frame_routing_id)
+    : global_frame_routing_id_(global_frame_routing_id) {}
+
+}  // namespace performance_manager
diff --git a/components/resources/terms/terms_ar.html b/components/resources/terms/terms_ar.html
index b6a077e..36ee469 100644
--- a/components/resources/terms/terms_ar.html
+++ b/components/resources/terms/terms_ar.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  بنود الخدمة الإضافية لكل من متصفح Google Chrome و"نظام التشغيل Chrome"
-</h1>
+</h2>
 <p>
  يعني استخدامك لمتصفح Chrome أو "نظام التشغيل Chrome" موافقتك على بنود خدمة Google المتاحة على الرابط https://policies.google.com/terms وبنود الخدمة الإضافية لكل من متصفح Google Chrome و"نظام التشغيل Chrome".
 </p>
diff --git a/components/resources/terms/terms_bg.html b/components/resources/terms/terms_bg.html
index 1bd496c1..bcfaf72 100644
--- a/components/resources/terms/terms_bg.html
+++ b/components/resources/terms/terms_bg.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Допълнителни общи условия на Google Chrome и Chrome OS
-</h1>
+</h2>
 <p>
  С използването на Chrome или Chrome OS приемате Общите условия на Google на адрес https://policies.google.com/terms и настоящите Допълнителни общи условия на Google Chrome и Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_ca.html b/components/resources/terms/terms_ca.html
index 41e29fc..8d6570fd 100644
--- a/components/resources/terms/terms_ca.html
+++ b/components/resources/terms/terms_ca.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Condicions del servei addicionals de Google Chrome i Chrome OS
-</h1>
+</h2>
 <p>
  En utilitzar Chrome o Chrome OS, accepteu les Condicions del servei de Google, que podeu consultar a https://policies.google.com/terms, i aquestes Condicions del servei addicionals de Google Chrome i Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_cs.html b/components/resources/terms/terms_cs.html
index f73b498a..5fe1e01 100644
--- a/components/resources/terms/terms_cs.html
+++ b/components/resources/terms/terms_cs.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Dodatečné smluvní podmínky prohlížeče Google Chrome a systému Chrome OS
-</h1>
+</h2>
 <p>
  Používáním prohlížeče Chrome nebo systému Chrome OS vyjadřujete souhlas se smluvními podmínkami společnosti Google na adrese https://policies.google.com/terms a těmito dodatečnými smluvními podmínkami pro Google Chrome a Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_da.html b/components/resources/terms/terms_da.html
index 4bbcce3..a3f0f57 100644
--- a/components/resources/terms/terms_da.html
+++ b/components/resources/terms/terms_da.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Yderligere servicevilkår for Google Chrome og Chrome OS
-</h1>
+</h2>
 <p>
  Når du bruger Chrome eller Chrome OS, accepterer du Googles servicevilkår, som kan findes på https://policies.google.com/terms, og disse yderligere servicevilkår for Google Chrome og Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_de.html b/components/resources/terms/terms_de.html
index 6bdf771..f692ff4c 100644
--- a/components/resources/terms/terms_de.html
+++ b/components/resources/terms/terms_de.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Zusätzliche Nutzungsbedingungen für Google Chrome und Chrome OS
-</h1>
+</h2>
 <p>
  Wenn Sie Chrome oder Chrome OS nutzen, stimmen Sie damit den Nutzungsbedingungen von Google unter https://policies.google.com/terms sowie diesen zusätzlichen Nutzungsbedingungen für Google Chrome und Chrome OS zu.
 </p>
diff --git a/components/resources/terms/terms_el.html b/components/resources/terms/terms_el.html
index 5dc5b9f..d18e7cb 100644
--- a/components/resources/terms/terms_el.html
+++ b/components/resources/terms/terms_el.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Πρόσθετοι Όροι Παροχής Υπηρεσιών Google Chrome και Chrome OS
-</h1>
+</h2>
 <p>
  Χρησιμοποιώντας το Chrome ή το Chrome OS, συμφωνείτε με τους Όρους Παροχής Υπηρεσιών της Google που μπορείτε να βρείτε στη διεύθυνση https://policies.google.com/terms και με τους Πρόσθετους Όρους Παροχής Υπηρεσιών του Google Chrome και του Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_en-GB.html b/components/resources/terms/terms_en-GB.html
index 569331f..b9673196 100644
--- a/components/resources/terms/terms_en-GB.html
+++ b/components/resources/terms/terms_en-GB.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Google Chrome and Chrome OS additional Terms of Service
-</h1>
+</h2>
 <p>
  By using Chrome or Chrome OS, you agree to the Google Terms of Service located at https://policies.google.com/terms and these Google Chrome and Chrome OS additional Terms of Service.
 </p>
diff --git a/components/resources/terms/terms_en.html b/components/resources/terms/terms_en.html
index 961efd1..10fce772 100644
--- a/components/resources/terms/terms_en.html
+++ b/components/resources/terms/terms_en.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Google Chrome and Chrome OS Additional Terms of Service
-</h1>
+</h2>
 <p>
  By using Chrome or Chrome OS, you agree to the Google Terms of Service located at https://policies.google.com/terms and these Google Chrome and Chrome OS Additional Terms of Service.
 </p>
diff --git a/components/resources/terms/terms_es-419.html b/components/resources/terms/terms_es-419.html
index 013eb067..e9f4954 100644
--- a/components/resources/terms/terms_es-419.html
+++ b/components/resources/terms/terms_es-419.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Condiciones del Servicio Adicionales de Google Chrome y el Sistema operativo Chrome
-</h1>
+</h2>
 <p>
  Al usar Chrome o el Sistema operativo Chrome, confirma que acepta las Condiciones del Servicio de Google (que se encuentran en https://policies.google.com/terms) y estas Condiciones del Servicio Adicionales de Google Chrome y el Sistema operativo Chrome.
 </p>
diff --git a/components/resources/terms/terms_es.html b/components/resources/terms/terms_es.html
index c5b5ac7da..4ba7684 100644
--- a/components/resources/terms/terms_es.html
+++ b/components/resources/terms/terms_es.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Términos del Servicio Adicionales de Google Chrome y Chrome OS
-</h1>
+</h2>
 <p>
  Al utilizar Google Chrome o Chrome OS, aceptas los Términos del Servicio de Google disponibles en https://policies.google.com/terms y estos Términos del Servicio Adicionales de Google Chrome y Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_et.html b/components/resources/terms/terms_et.html
index ae3acfa4..a853884 100644
--- a/components/resources/terms/terms_et.html
+++ b/components/resources/terms/terms_et.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Google Chrome'i ja Chrome OS-i lisateenusetingimused
-</h1>
+</h2>
 <p>
  Kasutades Chrome'i või Chrome OS-i, nõustute Google'i teenusetingimustega, mis asuvad saidil https://policies.google.com/terms, ning Google Chrome'i ja Chrome OS-i lisateenusetingimustega.
 </p>
diff --git a/components/resources/terms/terms_fa.html b/components/resources/terms/terms_fa.html
index 7af3d039..969e867 100644
--- a/components/resources/terms/terms_fa.html
+++ b/components/resources/terms/terms_fa.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  شرایط خدمات تکمیلی Google Chrome و «سیستم‌عامل Chrome»
-</h1>
+</h2>
 <p>
  درصورت استفاده از Chrome یا «سیستم‌عامل Chrome»، با «شرایط و ضوابط Google» موجود در https://policies.google.com/terms و این «شرایط خدمات تکمیلی» Google Chrome و «سیستم‌عامل Chrome» موافقت می‌کنید.
 </p>
diff --git a/components/resources/terms/terms_fi.html b/components/resources/terms/terms_fi.html
index 592656e46..82da5fc 100644
--- a/components/resources/terms/terms_fi.html
+++ b/components/resources/terms/terms_fi.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Google Chromen ja Chrome-käyttöjärjestelmän lisäkäyttöehdot
-</h1>
+</h2>
 <p>
  Käyttämällä Chromea tai Chrome-käyttöjärjestelmää hyväksyt osoitteessa https://policies.google.com/terms olevat Googlen käyttöehdot sekä nämä Google Chromen ja Chrome-käyttöjärjestelmän lisäkäyttöehdot.
 </p>
diff --git a/components/resources/terms/terms_fil.html b/components/resources/terms/terms_fil.html
index 3f6cc02..74b6e87 100644
--- a/components/resources/terms/terms_fil.html
+++ b/components/resources/terms/terms_fil.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Mga Karagdagang Tuntunin ng Serbisyo ng Google Chrome at Chrome OS
-</h1>
+</h2>
 <p>
  Sa paggamit sa Chrome o Chrome OS, sumasang-ayon ka sa Mga Tuntunin ng Serbisyo ng Google na makikita sa https://policies.google.com/terms at sa Mga Karagdagang Tuntunin ng Serbisyo ng Google Chrome at Chrome OS na ito.
 </p>
diff --git a/components/resources/terms/terms_fr.html b/components/resources/terms/terms_fr.html
index a2ca4b4..5b8238e 100644
--- a/components/resources/terms/terms_fr.html
+++ b/components/resources/terms/terms_fr.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Conditions d'utilisation supplémentaires de Google Chrome et Chrome OS
-</h1>
+</h2>
 <p>
  En utilisant Chrome ou Chrome OS, vous acceptez les Conditions d'utilisation de Google disponibles sur https://policies.google.com/terms et les présentes Conditions d'utilisation supplémentaires de Google Chrome et Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_he.html b/components/resources/terms/terms_he.html
index c6c3891..91269079 100644
--- a/components/resources/terms/terms_he.html
+++ b/components/resources/terms/terms_he.html
@@ -1,6 +1,21 @@
-<h1 id="google-chrome-terms-of-service">
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+"http://www.w3.org/TR/html4/loose.dtd">
+<html DIR="RTL">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta name="viewport" content="initial-scale=1.0">
+<title>תנאים והגבלות נוספים של Google Chrome ו-Chrome OS</title>
+<style>
+:root { color-scheme: light dark }
+body { font-family:Arial; font-size:13px; }
+h2 { font-size:1em; margin-top:0 }
+</style>
+</head>
+
+<body>
+<h2>
  תנאים והגבלות נוספים של Google Chrome ו-Chrome OS
-</h1>
+</h2>
 <p>
  שימוש ב-Chrome או ב-Chrome OS מצידך מבטא את הסכמתך לתנאים ולהגבלות של Google, המפורטים בכתובת https://policies.google.com/terms, ולתנאים ולהגבלות הנוספים של Google Chrome ושל Chrome OS, המפורטים כאן.
 </p>
@@ -157,5 +172,5 @@
   מוצר זה מורשה במסגרת רישיון תיק הפטנטים של MPEG-4 VISUAL לשימוש אישי ולשימוש שאינו מסחרי בידי צרכן, למטרות הבאות: (1) קידוד וידאו בהתאם לתקן MPEG-4 VISUAL (להלן: "וידאו MPEG-4") ו/או (2) פענוח קוד של וידאו MPEG-4 שקוּדד בידי צרכן העוסק בפעילות אישית ושאינה מסחרית ו/או שהתקבל מסַפָּק וידאו המחזיק ברישיון מטעם MPEG LA לסַפֵּק וידאו MPEG-4. לא מוענק רישיון לשימוש אחר כלשהו, ולא ישתמע כאילו מוענק רישיון כזה. ניתן לקבל מידע נוסף – לרבות מידע הנוגע לרישיונות, לשימוש פנימי ומסחרי ולשימוש לצורכי קידום מכירות – מחברת .MPEG LA, LLC בכתובת HTTP://WWW.MPEGLA.COM.
  </p>
 </section>
-
-<title>תנאים והגבלות נוספים של Google Chrome ו-Chrome OS</title>
+</body>
+</html>
\ No newline at end of file
diff --git a/components/resources/terms/terms_hi.html b/components/resources/terms/terms_hi.html
index 2f30633b..7a1f3ad 100644
--- a/components/resources/terms/terms_hi.html
+++ b/components/resources/terms/terms_hi.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Google Chrome और Chrome OS की सेवा की अतिरिक्त शर्तें
-</h1>
+</h2>
 <p>
  Chrome या Chrome OS इस्तेमाल करने का मतलब है कि आप https://policies.google.com/terms पर दी गई Google सेवा की शर्तों से सहमत हैं. इसका मतलब यह भी है कि आप Google Chrome और Chrome OS की सेवा की इन अतिरिक्त शर्तों से भी सहमत हैं.
 </p>
diff --git a/components/resources/terms/terms_hr.html b/components/resources/terms/terms_hr.html
index 8dce721..6f7b50f 100644
--- a/components/resources/terms/terms_hr.html
+++ b/components/resources/terms/terms_hr.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Dodatni uvjeti pružanja usluge za Google Chrome i Chrome OS
-</h1>
+</h2>
 <p>
  Korištenjem Chromea ili OS Chromea prihvaćate Googleove uvjete pružanja usluge na https://policies.google.com/terms i ove Dodatne uvjete pružanja usluge za Google Chrome i OS Chrome.
 </p>
diff --git a/components/resources/terms/terms_hu.html b/components/resources/terms/terms_hu.html
index 7c7d6ee..2a07565 100644
--- a/components/resources/terms/terms_hu.html
+++ b/components/resources/terms/terms_hu.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  A Google Chrome és a Chrome OS Kiegészítő Általános Szerződési Feltételei
-</h1>
+</h2>
 <p>
  A Chrome vagy a Chrome OS használatával Ön elfogadja a https://policies.google.com/terms oldalon hozzáférhető Google Általános Szerződési Feltételeket, továbbá a Google Chrome és a Chrome OS jelen Kiegészítő Általános Szerződési Feltételeit.
 </p>
diff --git a/components/resources/terms/terms_id.html b/components/resources/terms/terms_id.html
index e44d962..38b9a27 100644
--- a/components/resources/terms/terms_id.html
+++ b/components/resources/terms/terms_id.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Persyaratan Layanan Tambahan Google Chrome dan Chrome OS
-</h1>
+</h2>
 <p>
  Dengan menggunakan Chrome atau Chrome OS, Anda menyetujui Persyaratan Layanan Google yang ada di https://policies.google.com/terms serta Persyaratan Layanan Tambahan Google Chrome dan Chrome OS ini.
 </p>
diff --git a/components/resources/terms/terms_ja.html b/components/resources/terms/terms_ja.html
index 18f599f..0664261 100644
--- a/components/resources/terms/terms_ja.html
+++ b/components/resources/terms/terms_ja.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Google Chrome および Chrome OS 追加利用規約
-</h1>
+</h2>
 <p>
  Chrome または Chrome OS を使用することにより、Google 利用規約 https://policies.google.com/terms と、この Google Chrome および Chrome OS 追加利用規約に同意したことになります。
 </p>
diff --git a/components/resources/terms/terms_ko.html b/components/resources/terms/terms_ko.html
index 0ab3297..ea59832d 100644
--- a/components/resources/terms/terms_ko.html
+++ b/components/resources/terms/terms_ko.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Chrome 및 Chrome OS 추가 서비스 약관
-</h1>
+</h2>
 <p>
  Chrome 또는 Chrome OS를 사용하면 Google 서비스 약관(https://policies.google.com/terms) 및 다음 Chrome 및 Chrome OS 추가 서비스 약관에 동의하는 것으로 간주됩니다.
 </p>
diff --git a/components/resources/terms/terms_lt.html b/components/resources/terms/terms_lt.html
index d9fefa0..d68076f4 100644
--- a/components/resources/terms/terms_lt.html
+++ b/components/resources/terms/terms_lt.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  „Google Chrome“ ir „Chrome“ OS papildomos paslaugų teikimo sąlygos
-</h1>
+</h2>
 <p>
  Naudodami „Chrome“ arba „Chrome“ OS sutinkate su „Google“ paslaugų teikimo sąlygomis, pateiktomis adresu https://policies.google.com/terms, ir šiomis „Google Chrome“ bei „Chrome“ OS papildomomis paslaugų teikimo sąlygomis.
 </p>
diff --git a/components/resources/terms/terms_lv.html b/components/resources/terms/terms_lv.html
index 4cd9310..b4f84417 100644
--- a/components/resources/terms/terms_lv.html
+++ b/components/resources/terms/terms_lv.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Google Chrome un Chrome OS pakalpojumu sniegšanas papildu noteikumi
-</h1>
+</h2>
 <p>
  Izmantojot pārlūkprogrammu Chrome vai operētājsistēmu Chrome OS, jūs piekrītat Google pakalpojumu sniegšanas noteikumiem, kas norādīti vietnē https://policies.google.com/terms, un šiem Google Chrome un Chrome OS pakalpojumu sniegšanas papildu noteikumiem.
 </p>
diff --git a/components/resources/terms/terms_nb.html b/components/resources/terms/terms_nb.html
index 8c4a6c1..39c7178 100644
--- a/components/resources/terms/terms_nb.html
+++ b/components/resources/terms/terms_nb.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Tilleggsvilkår for bruk av Google Chrome og Chrome OS
-</h1>
+</h2>
 <p>
  Ved å bruke Chrome eller Chrome OS godtar du Googles vilkår for bruk, som du finner på https://policies.google.com/terms, samt disse tilleggsvilkårene for bruk av Google Chrome og Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_nl.html b/components/resources/terms/terms_nl.html
index e3649bc..91b51807 100644
--- a/components/resources/terms/terms_nl.html
+++ b/components/resources/terms/terms_nl.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Aanvullende servicevoorwaarden van Google Chrome en Chrome OS
-</h1>
+</h2>
 <p>
  Als u Chrome of Chrome OS gebruikt, gaat u akkoord met de Servicevoorwaarden van Google die te vinden zijn op https://policies.google.com/terms en met deze Aanvullende servicevoorwaarden van Google Chrome en Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_pl.html b/components/resources/terms/terms_pl.html
index 661bbebf..1c71e78 100644
--- a/components/resources/terms/terms_pl.html
+++ b/components/resources/terms/terms_pl.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Dodatkowe warunki korzystania z Google Chrome i Chrome OS
-</h1>
+</h2>
 <p>
  Używając Chrome lub Chrome OS, użytkownik wyraża zgodę na Warunki korzystania z usług Google dostępne na stronie https://policies.google.com/terms oraz niniejsze Dodatkowe warunki korzystania z Google Chrome i Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_pt-BR.html b/components/resources/terms/terms_pt-BR.html
index b16527d6..5fca110f 100644
--- a/components/resources/terms/terms_pt-BR.html
+++ b/components/resources/terms/terms_pt-BR.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Termos de Serviço adicionais do Google Chrome e do Chrome OS
-</h1>
+</h2>
 <p>
  Ao usar o Chrome ou o Chrome OS, você concorda com os Termos de Serviço do Google localizados em https://policies.google.com/terms e com estes Termos de Serviço adicionais do Google Chrome e do Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_pt-PT.html b/components/resources/terms/terms_pt-PT.html
index 4a9537d..e47a41c 100644
--- a/components/resources/terms/terms_pt-PT.html
+++ b/components/resources/terms/terms_pt-PT.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Termos de Utilização Adicionais do Google Chrome e do Chrome OS
-</h1>
+</h2>
 <p>
  Ao utilizar o Chrome ou o Chrome OS, aceita os Termos de Utilização do Google localizados em https://policies.google.com/terms?hl=pt-PT e estes Termos de Utilização Adicionais do Google Chrome e do Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_ro.html b/components/resources/terms/terms_ro.html
index b510ded..3aa5bea 100644
--- a/components/resources/terms/terms_ro.html
+++ b/components/resources/terms/terms_ro.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Termenii și condițiile suplimentare pentru Google Chrome și Sistemul de operare Chrome
-</h1>
+</h2>
 <p>
  Dacă folosești Chrome sau Sistemul de operare Chrome, ești de acord cu Termenii și condițiile Google de la https://policies.google.com/terms și cu acest set de Termeni și condiții suplimentare pentru Google Chrome și Sistemul de operare Chrome.
 </p>
diff --git a/components/resources/terms/terms_ru.html b/components/resources/terms/terms_ru.html
index ef41866f..f02062f0 100644
--- a/components/resources/terms/terms_ru.html
+++ b/components/resources/terms/terms_ru.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Дополнительные условия использования Chrome и Chrome OS
-</h1>
+</h2>
 <p>
  Используя Chrome или Chrome OS, Вы принимаете Условия использования Google, опубликованные на странице https://policies.google.com/terms, а также настоящие Дополнительные условия использования Chrome и Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_sk.html b/components/resources/terms/terms_sk.html
index eb79623..969dcf30 100644
--- a/components/resources/terms/terms_sk.html
+++ b/components/resources/terms/terms_sk.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Dodatočné zmluvné podmienky prehliadača Chrome a systému Chrome OS
-</h1>
+</h2>
 <p>
  Používaním prehliadača Chrome alebo systému Chrome OS vyjadrujete súhlas so zmluvnými podmienkami spoločnosti Google na adrese https://policies.google.com/terms a týmito dodatočnými zmluvnými podmienkami prehliadača Google Chrome a systému Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_sl.html b/components/resources/terms/terms_sl.html
index 0404df9c..8f4de718 100644
--- a/components/resources/terms/terms_sl.html
+++ b/components/resources/terms/terms_sl.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Dodatni pogoji za Google Chrome in Chrome OS
-</h1>
+</h2>
 <p>
  Z uporabo Chroma in sistema Chrome OS se strinjate z Googlovimi pogoji storitve, objavljenimi na https://policies.google.com/terms, in temi dodatnimi pogoji storitve za Google Chrome in Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_sr.html b/components/resources/terms/terms_sr.html
index 0069631..a3b79885 100644
--- a/components/resources/terms/terms_sr.html
+++ b/components/resources/terms/terms_sr.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Додатни услови коришћења услуге за Google Chrome и Chrome ОС
-</h1>
+</h2>
 <p>
  Коришћењем Chrome-а или Chrome ОС-а прихватате Google услове коришћења услуге који се налазе на https://policies.google.com/terms и ове додатне услове коришћења услуге за Google Chrome и Chrome ОС.
 </p>
diff --git a/components/resources/terms/terms_sv.html b/components/resources/terms/terms_sv.html
index 842d6ae..e70de66 100644
--- a/components/resources/terms/terms_sv.html
+++ b/components/resources/terms/terms_sv.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Ytterligare användarvillkor för Google Chrome och Chrome OS
-</h1>
+</h2>
 <p>
  Genom att använda Chrome eller Chrome OS godkänner du dessa ytterligare användarvillkor för Google Chrome och Chrome OS samt Googles användarvillkor, som finns här: https://policies.google.com/terms.
 </p>
diff --git a/components/resources/terms/terms_th.html b/components/resources/terms/terms_th.html
index 08286ce..b10fafd2 100644
--- a/components/resources/terms/terms_th.html
+++ b/components/resources/terms/terms_th.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  ข้อกำหนดในการให้บริการเพิ่มเติมของ Google Chrome และ Chrome OS
-</h1>
+</h2>
 <p>
  การใช้ Chrome หรือ Chrome OS หมายความว่า คุณยอมรับข้อกำหนดในการให้บริการของ Google ซึ่งอยู่ที่ https://policies.google.com/terms และข้อกำหนดในการให้บริการเพิ่มเติมของ Google Chrome และ Chrome OS เหล่านี้
 </p>
diff --git a/components/resources/terms/terms_tr.html b/components/resources/terms/terms_tr.html
index afcb56b3..0045cd9 100644
--- a/components/resources/terms/terms_tr.html
+++ b/components/resources/terms/terms_tr.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Google Chrome ve Chrome OS Ek Hizmet Şartları
-</h1>
+</h2>
 <p>
  Chrome veya Chrome OS'u kullanarak https://policies.google.com/terms adresinde bulunan Google Hizmet Şartları'nı ve bu Google Chrome ile Chrome OS Ek Hizmet Şartları'nı kabul etmiş olursunuz.
 </p>
diff --git a/components/resources/terms/terms_uk.html b/components/resources/terms/terms_uk.html
index 6ce5183..8df7671 100644
--- a/components/resources/terms/terms_uk.html
+++ b/components/resources/terms/terms_uk.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Додаткові умови використання Google Chrome і ОС Chrome
-</h1>
+</h2>
 <p>
  Використовуючи Chrome або ОС Chrome, ви погоджуєтесь із Загальними положеннями та умовами Google на сторінці https://policies.google.com/terms і цими Додатковими умовами використання Google Chrome та ОС Chrome.
 </p>
diff --git a/components/resources/terms/terms_vi.html b/components/resources/terms/terms_vi.html
index 59653f4..45964d4 100644
--- a/components/resources/terms/terms_vi.html
+++ b/components/resources/terms/terms_vi.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Điều khoản dịch vụ bổ sung của Google Chrome và Chrome OS
-</h1>
+</h2>
 <p>
  Bằng việc sử dụng Chrome hoặc Chrome OS, bạn đồng ý với Điều khoản dịch vụ của Google có tại https://policies.google.com/terms cũng như các Điều khoản dịch vụ bổ sung sau đây của Google Chrome và Chrome OS.
 </p>
diff --git a/components/resources/terms/terms_zh-CN.html b/components/resources/terms/terms_zh-CN.html
index b8de987..f6dfb93 100644
--- a/components/resources/terms/terms_zh-CN.html
+++ b/components/resources/terms/terms_zh-CN.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Google Chrome 和 Chrome 操作系统附加服务条款
-</h1>
+</h2>
 <p>
  使用 Chrome 或 Chrome 操作系统即表示您同意接受《Google 服务条款》(全文请见 https://policies.google.com/terms)以及这些 Google Chrome 和 Chrome 操作系统附加服务条款。
 </p>
diff --git a/components/resources/terms/terms_zh-TW.html b/components/resources/terms/terms_zh-TW.html
index 43a4782..d57570fa 100644
--- a/components/resources/terms/terms_zh-TW.html
+++ b/components/resources/terms/terms_zh-TW.html
@@ -13,9 +13,9 @@
 </head>
 
 <body>
-<h1 id="google-chrome-terms-of-service">
+<h2>
  Google Chrome 和 Chrome 作業系統的《附加服務條款》
-</h1>
+</h2>
 <p>
  使用 Chrome 或 Chrome 作業系統,即表示您同意 https://policies.google.com/terms 所述的《Google 服務條款》,以及 Google Chrome 和 Chrome 作業系統的《附加服務條款》。
 </p>
diff --git a/components/safe_browsing/content/password_protection/metrics_util.h b/components/safe_browsing/content/password_protection/metrics_util.h
index 4a288d4..cdc088f3e 100644
--- a/components/safe_browsing/content/password_protection/metrics_util.h
+++ b/components/safe_browsing/content/password_protection/metrics_util.h
@@ -23,6 +23,7 @@
 extern const char kEnterprisePasswordInterstitialHistogram[];
 extern const char kEnterprisePasswordPageInfoHistogram[];
 extern const char kEnterprisePasswordWarningDialogHistogram[];
+extern const char kSavedPasswordPageInfoHistogram[];
 extern const char kGmailNonSyncPasswordInterstitialHistogram[];
 extern const char kGmailSyncPasswordPageInfoHistogram[];
 extern const char kGmailNonSyncPasswordPageInfoHistogram[];
diff --git a/components/services/storage/public/mojom/service_worker_storage_control.mojom b/components/services/storage/public/mojom/service_worker_storage_control.mojom
index 4dd57e1..ed47bedf 100644
--- a/components/services/storage/public/mojom/service_worker_storage_control.mojom
+++ b/components/services/storage/public/mojom/service_worker_storage_control.mojom
@@ -41,8 +41,9 @@
   // Reads the response head of the resource associated with this reader.
   ReadResponseHead() =>
       (int32 status, network.mojom.URLResponseHead response_head);
-  // TODO(crbug.com/1055677): Add ways to read the content and the metadata of
-  // the script.
+  // Reads the content of the resource associated with this reader.
+  ReadData(int64 size) => (handle<data_pipe_consumer> pipe);
+  // TODO(crbug.com/1055677): Add ways to read the metadata of the script.
 };
 
 // An interface that writes a service worker script (resource) to storage.
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc b/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
index e75b104..3107253 100644
--- a/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
+++ b/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
@@ -25,56 +25,6 @@
 
 namespace content {
 
-namespace {
-
-void ReadDataPipeInternal(mojo::DataPipeConsumerHandle handle,
-                          std::string* result,
-                          base::OnceClosure quit_closure) {
-  while (true) {
-    uint32_t num_bytes;
-    const void* buffer = nullptr;
-    MojoResult rv =
-        handle.BeginReadData(&buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
-    switch (rv) {
-      case MOJO_RESULT_BUSY:
-      case MOJO_RESULT_INVALID_ARGUMENT:
-        NOTREACHED();
-        return;
-      case MOJO_RESULT_FAILED_PRECONDITION:
-        std::move(quit_closure).Run();
-        return;
-      case MOJO_RESULT_SHOULD_WAIT:
-        base::ThreadTaskRunnerHandle::Get()->PostTask(
-            FROM_HERE, base::BindOnce(&ReadDataPipeInternal, handle, result,
-                                      std::move(quit_closure)));
-        return;
-      case MOJO_RESULT_OK:
-        EXPECT_NE(nullptr, buffer);
-        EXPECT_GT(num_bytes, 0u);
-        uint32_t before_size = result->size();
-        result->append(static_cast<const char*>(buffer), num_bytes);
-        uint32_t read_size = result->size() - before_size;
-        EXPECT_EQ(num_bytes, read_size);
-        rv = handle.EndReadData(read_size);
-        EXPECT_EQ(MOJO_RESULT_OK, rv);
-        break;
-    }
-  }
-  NOTREACHED();
-  return;
-}
-
-std::string ReadDataPipe(mojo::ScopedDataPipeConsumerHandle handle) {
-  EXPECT_TRUE(handle.is_valid());
-  std::string result;
-  base::RunLoop loop;
-  ReadDataPipeInternal(handle.get(), &result, loop.QuitClosure());
-  loop.Run();
-  return result;
-}
-
-}  // namespace
-
 class ExpectedScriptInfo {
  public:
   ExpectedScriptInfo(
diff --git a/content/browser/service_worker/service_worker_resource_ops.cc b/content/browser/service_worker/service_worker_resource_ops.cc
index 45468d6..eec4a701 100644
--- a/content/browser/service_worker/service_worker_resource_ops.cc
+++ b/content/browser/service_worker/service_worker_resource_ops.cc
@@ -5,6 +5,9 @@
 #include "content/browser/service_worker/service_worker_resource_ops.h"
 
 #include "content/browser/service_worker/service_worker_loader_helpers.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "services/network/public/cpp/net_adapters.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
 
 namespace content {
 
@@ -75,6 +78,103 @@
 
 }  // namespace
 
+class ServiceWorkerResourceReaderImpl::DataReader {
+ public:
+  DataReader(base::WeakPtr<ServiceWorkerResourceReaderImpl> owner,
+             size_t total_bytes_to_read,
+             mojo::ScopedDataPipeProducerHandle producer_handle)
+      : owner_(std::move(owner)),
+        total_bytes_to_read_(total_bytes_to_read),
+        producer_handle_(std::move(producer_handle)),
+        watcher_(FROM_HERE,
+                 mojo::SimpleWatcher::ArmingPolicy::MANUAL,
+                 base::SequencedTaskRunnerHandle::Get()) {
+    watcher_.Watch(producer_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
+                   base::BindRepeating(&DataReader::OnWritable,
+                                       weak_factory_.GetWeakPtr()));
+    watcher_.ArmOrNotify();
+  }
+  ~DataReader() = default;
+
+  DataReader(const DataReader&) = delete;
+  DataReader operator=(const DataReader&) = delete;
+
+ private:
+  void OnWritable(MojoResult) {
+    DCHECK(producer_handle_.is_valid());
+    DCHECK(!pending_buffer_);
+
+    if (!owner_) {
+      Complete(net::ERR_ABORTED);
+      return;
+    }
+
+    uint32_t num_bytes = 0;
+    MojoResult rv = network::NetToMojoPendingBuffer::BeginWrite(
+        &producer_handle_, &pending_buffer_, &num_bytes);
+    switch (rv) {
+      case MOJO_RESULT_INVALID_ARGUMENT:
+      case MOJO_RESULT_BUSY:
+        NOTREACHED();
+        return;
+      case MOJO_RESULT_FAILED_PRECONDITION:
+        Complete(net::ERR_ABORTED);
+        return;
+      case MOJO_RESULT_SHOULD_WAIT:
+        watcher_.ArmOrNotify();
+        return;
+      case MOJO_RESULT_OK:
+        // |producer__handle_| must have been taken by |pending_buffer_|.
+        DCHECK(pending_buffer_);
+        DCHECK(!producer_handle_.is_valid());
+        break;
+    }
+
+    num_bytes = std::min(num_bytes, blink::BlobUtils::GetDataPipeChunkSize());
+    auto buffer =
+        base::MakeRefCounted<network::NetToMojoIOBuffer>(pending_buffer_.get());
+    owner_->reader_->ReadData(
+        buffer.get(), num_bytes,
+        base::BindOnce(&DataReader::DidReadData, weak_factory_.GetWeakPtr()));
+  }
+
+  void DidReadData(int read_bytes) {
+    if (read_bytes < 0) {
+      Complete(read_bytes);
+      return;
+    }
+
+    producer_handle_ = pending_buffer_->Complete(read_bytes);
+    DCHECK(producer_handle_.is_valid());
+    pending_buffer_.reset();
+    current_bytes_read_ += read_bytes;
+
+    if (read_bytes == 0 || current_bytes_read_ == total_bytes_to_read_) {
+      // All data has been read.
+      Complete(current_bytes_read_);
+      return;
+    }
+    watcher_.ArmOrNotify();
+  }
+
+  void Complete(int status) {
+    watcher_.Cancel();
+    producer_handle_.reset();
+    if (owner_) {
+      owner_->DidReadDataComplete();
+    }
+  }
+
+  base::WeakPtr<ServiceWorkerResourceReaderImpl> owner_;
+  const size_t total_bytes_to_read_;
+  size_t current_bytes_read_ = 0;
+  mojo::ScopedDataPipeProducerHandle producer_handle_;
+  mojo::SimpleWatcher watcher_;
+  scoped_refptr<network::NetToMojoPendingBuffer> pending_buffer_;
+
+  base::WeakPtrFactory<DataReader> weak_factory_{this};
+};
+
 ServiceWorkerResourceReaderImpl::ServiceWorkerResourceReaderImpl(
     std::unique_ptr<ServiceWorkerResponseReader> reader)
     : reader_(std::move(reader)) {
@@ -91,6 +191,33 @@
                                                std::move(callback)));
 }
 
+void ServiceWorkerResourceReaderImpl::ReadData(int64_t size,
+                                               ReadDataCallback callback) {
+  MojoCreateDataPipeOptions options;
+  options.struct_size = sizeof(MojoCreateDataPipeOptions);
+  options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+  options.element_num_bytes = 1;
+  options.capacity_num_bytes = blink::BlobUtils::GetDataPipeCapacity(size);
+
+  mojo::ScopedDataPipeConsumerHandle consumer_handle;
+  mojo::ScopedDataPipeProducerHandle producer_handle;
+  MojoResult rv =
+      mojo::CreateDataPipe(&options, &producer_handle, &consumer_handle);
+  if (rv != MOJO_RESULT_OK) {
+    std::move(callback).Run(mojo::ScopedDataPipeConsumerHandle());
+    return;
+  }
+
+  data_reader_ = std::make_unique<DataReader>(weak_factory_.GetWeakPtr(), size,
+                                              std::move(producer_handle));
+  std::move(callback).Run(std::move(consumer_handle));
+}
+
+void ServiceWorkerResourceReaderImpl::DidReadDataComplete() {
+  DCHECK(data_reader_);
+  data_reader_.reset();
+}
+
 ServiceWorkerResourceWriterImpl::ServiceWorkerResourceWriterImpl(
     std::unique_ptr<ServiceWorkerResponseWriter> writer)
     : writer_(std::move(writer)) {
diff --git a/content/browser/service_worker/service_worker_resource_ops.h b/content/browser/service_worker/service_worker_resource_ops.h
index c2f9b3c..5584550c 100644
--- a/content/browser/service_worker/service_worker_resource_ops.h
+++ b/content/browser/service_worker/service_worker_resource_ops.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_RESOURCE_OPS_H_
 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_RESOURCE_OPS_H_
 
+#include "base/memory/weak_ptr.h"
 #include "components/services/storage/public/mojom/service_worker_storage_control.mojom.h"
 #include "content/browser/service_worker/service_worker_disk_cache.h"
 
@@ -31,8 +32,16 @@
  private:
   // storage::mojom::ServiceWorkerResourceReader implementations:
   void ReadResponseHead(ReadResponseHeadCallback callback) override;
+  void ReadData(int64_t size, ReadDataCallback callback) override;
+
+  void DidReadDataComplete();
 
   const std::unique_ptr<ServiceWorkerResponseReader> reader_;
+
+  class DataReader;
+  std::unique_ptr<DataReader> data_reader_;
+
+  base::WeakPtrFactory<ServiceWorkerResourceReaderImpl> weak_factory_{this};
 };
 
 // The implementation of storage::mojom::ServiceWorkerResourceWriter.
diff --git a/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc b/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc
index 7810f53..771d8f5b 100644
--- a/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc
+++ b/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc
@@ -9,8 +9,10 @@
 #include "base/test/bind_test_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/service_worker/service_worker_storage.h"
+#include "content/browser/service_worker/service_worker_test_utils.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_utils.h"
+#include "mojo/public/cpp/system/data_pipe_utils.h"
 #include "net/disk_cache/disk_cache.h"
 #include "net/http/http_util.h"
 #include "net/test/cert_test_util.h"
@@ -40,6 +42,21 @@
   return return_value;
 }
 
+std::string ReadResponseData(
+    storage::mojom::ServiceWorkerResourceReader* reader,
+    int data_size) {
+  mojo::ScopedDataPipeConsumerHandle data_consumer;
+  base::RunLoop loop;
+  reader->ReadData(data_size, base::BindLambdaForTesting(
+                                  [&](mojo::ScopedDataPipeConsumerHandle pipe) {
+                                    data_consumer = std::move(pipe);
+                                    loop.Quit();
+                                  }));
+  loop.Run();
+
+  return ReadDataPipe(std::move(data_consumer));
+}
+
 int WriteResponseHead(storage::mojom::ServiceWorkerResourceWriter* writer,
                       network::mojom::URLResponseHeadPtr response_head) {
   int return_value;
@@ -446,6 +463,7 @@
   // Write content.
   {
     mojo_base::BigBuffer data(base::as_bytes(base::make_span(kData)));
+    int data_size = data.size();
 
     int result = WriteResponseData(writer.get(), std::move(data));
     ASSERT_EQ(data_size, result);
@@ -454,7 +472,7 @@
   mojo::Remote<storage::mojom::ServiceWorkerResourceReader> reader =
       CreateResourceReader(resource_id);
 
-  // Read the response head.
+  // Read the response head and the content.
   {
     network::mojom::URLResponseHeadPtr response_head;
     int result = ReadResponseHead(reader.get(), response_head);
@@ -465,9 +483,12 @@
     EXPECT_TRUE(response_head->ssl_info->is_valid());
     EXPECT_EQ(response_head->ssl_info->cert->serial_number(),
               ssl_info.cert->serial_number());
+
+    std::string data = ReadResponseData(reader.get(), data_size);
+    EXPECT_EQ(data, kData);
   }
 
-  // TODO(crbug.com/1055677): Read and check the content of the resource.
+  // TODO(crbug.com/1055677): Write metadata, read it then check the metadata.
 }
 
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_test_utils.cc b/content/browser/service_worker/service_worker_test_utils.cc
index 6874b503..f8a8c2b 100644
--- a/content/browser/service_worker/service_worker_test_utils.cc
+++ b/content/browser/service_worker/service_worker_test_utils.cc
@@ -872,4 +872,50 @@
   return true;
 }
 
+void ReadDataPipeInternal(mojo::DataPipeConsumerHandle handle,
+                          std::string* result,
+                          base::OnceClosure quit_closure) {
+  while (true) {
+    uint32_t num_bytes;
+    const void* buffer = nullptr;
+    MojoResult rv =
+        handle.BeginReadData(&buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
+    switch (rv) {
+      case MOJO_RESULT_BUSY:
+      case MOJO_RESULT_INVALID_ARGUMENT:
+        NOTREACHED();
+        return;
+      case MOJO_RESULT_FAILED_PRECONDITION:
+        std::move(quit_closure).Run();
+        return;
+      case MOJO_RESULT_SHOULD_WAIT:
+        base::ThreadTaskRunnerHandle::Get()->PostTask(
+            FROM_HERE, base::BindOnce(&ReadDataPipeInternal, handle, result,
+                                      std::move(quit_closure)));
+        return;
+      case MOJO_RESULT_OK:
+        EXPECT_NE(nullptr, buffer);
+        EXPECT_GT(num_bytes, 0u);
+        uint32_t before_size = result->size();
+        result->append(static_cast<const char*>(buffer), num_bytes);
+        uint32_t read_size = result->size() - before_size;
+        EXPECT_EQ(num_bytes, read_size);
+        rv = handle.EndReadData(read_size);
+        EXPECT_EQ(MOJO_RESULT_OK, rv);
+        break;
+    }
+  }
+  NOTREACHED();
+  return;
+}
+
+std::string ReadDataPipe(mojo::ScopedDataPipeConsumerHandle handle) {
+  EXPECT_TRUE(handle.is_valid());
+  std::string result;
+  base::RunLoop loop;
+  ReadDataPipeInternal(handle.get(), &result, loop.QuitClosure());
+  loop.Run();
+  return result;
+}
+
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_test_utils.h b/content/browser/service_worker/service_worker_test_utils.h
index 984c9d6..79e1ec6 100644
--- a/content/browser/service_worker/service_worker_test_utils.h
+++ b/content/browser/service_worker/service_worker_test_utils.h
@@ -417,6 +417,12 @@
                                    const std::string& expected_body);
 };
 
+// Reads all data from the given |handle| and returns data as a string.
+// This is similar to mojo::BlockingCopyToString() but a bit different. This
+// doesn't wait synchronously but keep posting a task when |handle| returns
+// MOJO_RESULT_SHOULD_WAIT.
+std::string ReadDataPipe(mojo::ScopedDataPipeConsumerHandle handle);
+
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_TEST_UTILS_H_
diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc
index b6931db..8a23a101 100644
--- a/content/renderer/media/media_factory.cc
+++ b/content/renderer/media/media_factory.cc
@@ -539,17 +539,14 @@
 #endif  // BUILDFLAG(ENABLE_MOJO_RENDERER)
 
 #if defined(OS_FUCHSIA)
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableFuchsiaAudioConsumer)) {
-    use_default_renderer_factory = false;
-    factory_selector->AddBaseFactory(
-        FactoryType::kFuchsia,
-        std::make_unique<FuchsiaRendererFactory>(
-            media_log, decoder_factory,
-            base::BindRepeating(&RenderThreadImpl::GetGpuFactories,
-                                base::Unretained(render_thread)),
-            render_frame_->GetBrowserInterfaceBroker()));
-  }
+  use_default_renderer_factory = false;
+  factory_selector->AddBaseFactory(
+      FactoryType::kFuchsia,
+      std::make_unique<FuchsiaRendererFactory>(
+          media_log, decoder_factory,
+          base::BindRepeating(&RenderThreadImpl::GetGpuFactories,
+                              base::Unretained(render_thread)),
+          render_frame_->GetBrowserInterfaceBroker()));
 #endif  // defined(OS_FUCHSIA)
 
   if (use_default_renderer_factory) {
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index 6a872eff..eefebeda 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -778,6 +778,7 @@
       testonly = true
       binary = ":content_shell"
       package_name_override = "content_shell"
+      manifest = "fuchsia/content_shell.cmx"
     }
 
     fuchsia_package_runner("content_shell_fuchsia") {
diff --git a/content/shell/fuchsia/content_shell.cmx b/content/shell/fuchsia/content_shell.cmx
new file mode 100644
index 0000000..912ae8b
--- /dev/null
+++ b/content/shell/fuchsia/content_shell.cmx
@@ -0,0 +1,32 @@
+{
+  "sandbox": {
+    "features": [
+      "deprecated-ambient-replace-as-executable",
+      "isolated-persistent-storage",
+      "isolated-temp",
+      "vulkan"
+    ],
+    "services": [
+      "fuchsia.accessibility.semantics.SemanticsManager",
+      "fuchsia.device.NameProvider",
+      "fuchsia.fonts.Provider",
+      "fuchsia.intl.PropertyProvider",
+      "fuchsia.logger.LogSink",
+      "fuchsia.media.Audio",
+      "fuchsia.media.SessionAudioConsumerFactory",
+      "fuchsia.media.drm.Widevine",
+      "fuchsia.mediacodec.CodecFactory",
+      "fuchsia.memorypressure.Provider",
+      "fuchsia.net.NameLookup",
+      "fuchsia.netstack.Netstack",
+      "fuchsia.posix.socket.Provider",
+      "fuchsia.process.Launcher",
+      "fuchsia.sys.Launcher",
+      "fuchsia.sysmem.Allocator",
+      "fuchsia.ui.input.ImeService",
+      "fuchsia.ui.input.ImeVisibilityService",
+      "fuchsia.ui.scenic.Scenic",
+      "fuchsia.vulkan.loader.Loader"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/device/bluetooth/strings/bluetooth_strings_hy.xtb b/device/bluetooth/strings/bluetooth_strings_hy.xtb
index ed2eaa9..37c8a212 100644
--- a/device/bluetooth/strings/bluetooth_strings_hy.xtb
+++ b/device/bluetooth/strings/bluetooth_strings_hy.xtb
@@ -14,7 +14,7 @@
 <translation id="430326050669417502">Ջոյսթիկ (<ph name="ADDRESS" />)</translation>
 <translation id="4698630591226285015"><ph name="DEVICE_NAME" />, աուդիո սարք</translation>
 <translation id="4986357476502426173"><ph name="DEVICE_NAME" />, տեսասարք</translation>
-<translation id="5271696982761495740">Գրասալիկ (<ph name="ADDRESS" />)</translation>
+<translation id="5271696982761495740">Պլանշետ (<ph name="ADDRESS" />)</translation>
 <translation id="5376363957846771741">Անհայտ կամ չաջակցվող սարք (<ph name="ADDRESS" />)</translation>
 <translation id="5716052956047449618"><ph name="DEVICE_NAME" />, մոդեմ</translation>
 <translation id="6459740836740815150"><ph name="DEVICE_NAME" />, ավտոմեքենայի աուդիո սարք</translation>
diff --git a/docs/sheriff.md b/docs/sheriff.md
index 4f2f56be..2a9b680 100644
--- a/docs/sheriff.md
+++ b/docs/sheriff.md
@@ -400,8 +400,9 @@
 ### Other Causes
 
 There are many other things that can go wrong, which are too individually rare
-and numerous to be listed here. Ask for help with diagnosis in Slack #sheriffing
-and hopefully someone else will be able to help you figure it out.
+and numerous to be listed here. Ask for help with diagnosis in
+[slack #sheriffing] and hopefully someone else will be able to help you figure
+it out.
 
 [CI console page]: https://ci.chromium.org/p/chromium/g/chromium/console
 [SlowTests]: https://cs.chromium.org/chromium/src/third_party/blink/web_tests/SlowTests
diff --git a/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc b/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
index a595bbd..cfd8529 100644
--- a/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
+++ b/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
@@ -492,8 +492,7 @@
   bool Finish() override {
     switch (write_type_) {
       case filter_list_converter::kExtension: {
-        TestRulesetInfo info = {kJSONRulesFilename,
-                                std::move(output_rules_list_)};
+        TestRulesetInfo info(kJSONRulesFilename, output_rules_list_);
         WriteManifestAndRuleset(output_path_, info, {} /* hosts */);
         break;
       }
diff --git a/extensions/common/api/declarative_net_request/dnr_manifest_unittest.cc b/extensions/common/api/declarative_net_request/dnr_manifest_unittest.cc
index 98c9e1f0..01cf1ff 100644
--- a/extensions/common/api/declarative_net_request/dnr_manifest_unittest.cc
+++ b/extensions/common/api/declarative_net_request/dnr_manifest_unittest.cc
@@ -32,10 +32,6 @@
 namespace declarative_net_request {
 namespace {
 
-constexpr char kJSONRulesFilename[] = "rules_file.json";
-const base::FilePath::CharType kJSONRulesetFilepath[] =
-    FILE_PATH_LITERAL("rules_file.json");
-
 std::string GetRuleResourcesKey() {
   return base::JoinString(
       {keys::kDeclarativeNetRequestKey, keys::kDeclarativeRuleResourcesKey},
@@ -59,7 +55,7 @@
 
   // Loads the extension and verifies that the manifest info is correctly set
   // up.
-  void LoadAndExpectSuccess(const std::vector<base::FilePath>& expected_paths) {
+  void LoadAndExpectSuccess(const std::vector<TestRulesetInfo>& info) {
     std::string error;
     scoped_refptr<Extension> extension = file_util::LoadExtension(
         temp_dir_.GetPath(), Manifest::UNPACKED, Extension::NO_FLAGS, &error);
@@ -68,20 +64,26 @@
 
     const std::vector<DNRManifestData::RulesetInfo>& rulesets =
         DNRManifestData::GetRulesets(*extension);
-    ASSERT_EQ(expected_paths.size(), rulesets.size());
+    ASSERT_EQ(info.size(), rulesets.size());
     for (size_t i = 0; i < rulesets.size(); ++i) {
       EXPECT_GE(rulesets[i].id, kMinValidStaticRulesetID);
-      EXPECT_EQ(rulesets[i].relative_path, expected_paths[i]);
+
+      // Compare normalized FilePaths instead of their string representations
+      // since different platforms represent path separators differently.
+      EXPECT_EQ(base::FilePath()
+                    .AppendASCII(info[i].relative_file_path)
+                    .NormalizePathSeparators(),
+                rulesets[i].relative_path);
     }
   }
 
-  void WriteManifestAndRuleset(
-      const base::Value& manifest,
-      const std::vector<base::FilePath>& ruleset_paths) {
+  void WriteManifestAndRuleset(const base::Value& manifest,
+                               const std::vector<TestRulesetInfo>& info) {
     EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
 
-    for (const auto& path : ruleset_paths) {
-      base::FilePath rules_path = temp_dir_.GetPath().Append(path);
+    for (const auto& ruleset : info) {
+      base::FilePath rules_path =
+          temp_dir_.GetPath().AppendASCII(ruleset.relative_file_path);
 
       // Create parent directory of |rules_path| if it doesn't exist.
       EXPECT_TRUE(base::CreateDirectory(rules_path.DirName()));
@@ -95,6 +97,10 @@
         .Serialize(manifest);
   }
 
+  TestRulesetInfo CreateDefaultRuleset() {
+    return TestRulesetInfo("rules_file.json", base::ListValue());
+  }
+
  private:
   base::ScopedTempDir temp_dir_;
   ScopedCurrentChannel channel_;
@@ -103,114 +109,66 @@
 };
 
 TEST_F(DNRManifestTest, EmptyRuleset) {
-  base::FilePath ruleset_path = base::FilePath(kJSONRulesetFilepath);
-  WriteManifestAndRuleset(*CreateManifest(kJSONRulesFilename), {ruleset_path});
-
-  LoadAndExpectSuccess({ruleset_path});
+  std::vector<TestRulesetInfo> rulesets({CreateDefaultRuleset()});
+  WriteManifestAndRuleset(*CreateManifest(rulesets), rulesets);
+  LoadAndExpectSuccess(rulesets);
 }
 
 TEST_F(DNRManifestTest, InvalidManifestKey) {
-  std::unique_ptr<base::DictionaryValue> manifest =
-      CreateManifest(kJSONRulesFilename);
+  std::vector<TestRulesetInfo> rulesets({CreateDefaultRuleset()});
+  std::unique_ptr<base::DictionaryValue> manifest = CreateManifest(rulesets);
   manifest->SetInteger(keys::kDeclarativeNetRequestKey, 3);
-  WriteManifestAndRuleset(*manifest, {base::FilePath(kJSONRulesetFilepath)});
+
+  WriteManifestAndRuleset(*manifest, rulesets);
   LoadAndExpectError(
       ErrorUtils::FormatErrorMessage(errors::kInvalidDeclarativeNetRequestKey,
                                      keys::kDeclarativeNetRequestKey));
 }
 
 TEST_F(DNRManifestTest, InvalidRulesFileKey) {
-  std::unique_ptr<base::DictionaryValue> manifest =
-      CreateManifest(kJSONRulesFilename);
+  std::vector<TestRulesetInfo> rulesets({CreateDefaultRuleset()});
+  std::unique_ptr<base::DictionaryValue> manifest = CreateManifest(rulesets);
   manifest->SetInteger(GetRuleResourcesKey(), 3);
-  WriteManifestAndRuleset(*manifest, {base::FilePath(kJSONRulesetFilepath)});
+
+  WriteManifestAndRuleset(*manifest, rulesets);
   LoadAndExpectError(ErrorUtils::FormatErrorMessage(
       errors::kInvalidDeclarativeRulesFileKey, keys::kDeclarativeNetRequestKey,
       keys::kDeclarativeRuleResourcesKey));
 }
 
 TEST_F(DNRManifestTest, ZeroRulesets) {
-  std::unique_ptr<base::DictionaryValue> manifest =
-      CreateManifest(kJSONRulesFilename);
-  manifest->SetList(GetRuleResourcesKey(), std::make_unique<base::ListValue>());
-
-  std::vector<base::FilePath> no_paths;
-  WriteManifestAndRuleset(*manifest, no_paths);
-  LoadAndExpectSuccess(no_paths);
+  std::vector<TestRulesetInfo> no_rulesets;
+  WriteManifestAndRuleset(*CreateManifest(no_rulesets), no_rulesets);
+  LoadAndExpectSuccess(no_rulesets);
 }
 
 TEST_F(DNRManifestTest, MultipleRulesFileSuccess) {
-  std::unique_ptr<base::DictionaryValue> manifest =
-      CreateManifest(kJSONRulesFilename);
-
-  ListBuilder rule_resources;
-
-  base::FilePath path1(FILE_PATH_LITERAL("file1.json"));
-  dnr_api::Ruleset ruleset;
-  ruleset.path = path1.AsUTF8Unsafe();
-  rule_resources.Append(ruleset.ToValue());
-
-  base::FilePath path2(FILE_PATH_LITERAL("file2.json"));
-  ruleset.path = path2.AsUTF8Unsafe();
-  rule_resources.Append(ruleset.ToValue());
-
-  base::FilePath path3(FILE_PATH_LITERAL("file3.json"));
-  ruleset.path = path3.AsUTF8Unsafe();
-  rule_resources.Append(ruleset.ToValue());
-
-  manifest->SetList(GetRuleResourcesKey(), rule_resources.Build());
-
-  std::vector<base::FilePath> paths = {path1, path2, path3};
-  WriteManifestAndRuleset(*manifest, paths);
-
-  LoadAndExpectSuccess(paths);
+  TestRulesetInfo ruleset_1("file1.json", base::ListValue());
+  TestRulesetInfo ruleset_2("file2.json", base::ListValue());
+  TestRulesetInfo ruleset_3("file3.json", base::ListValue());
+  std::vector<TestRulesetInfo> rulesets = {ruleset_1, ruleset_2, ruleset_3};
+  WriteManifestAndRuleset(*CreateManifest(rulesets), rulesets);
+  LoadAndExpectSuccess(rulesets);
 }
 
 TEST_F(DNRManifestTest, MultipleRulesFileInvalidPath) {
-  std::unique_ptr<base::DictionaryValue> manifest =
-      CreateManifest(kJSONRulesFilename);
+  TestRulesetInfo ruleset_1("file1.json", base::ListValue());
+  TestRulesetInfo ruleset_2("file2.json", base::ListValue());
 
-  ListBuilder rule_resources;
-
-  base::FilePath path1(FILE_PATH_LITERAL("file1.json"));
-  dnr_api::Ruleset ruleset;
-  ruleset.path = path1.AsUTF8Unsafe();
-  rule_resources.Append(ruleset.ToValue());
-
-  base::FilePath path2(FILE_PATH_LITERAL("file2.json"));
-  ruleset.path = path2.AsUTF8Unsafe();
-  rule_resources.Append(ruleset.ToValue());
-
-  manifest->SetList(GetRuleResourcesKey(), rule_resources.Build());
-
-  // Only persist |path1|.
-  WriteManifestAndRuleset(*manifest, {path1});
+  // Only persist |ruleset_1| on disk but include both in the manifest.
+  WriteManifestAndRuleset(*CreateManifest({ruleset_1, ruleset_2}), {ruleset_1});
 
   LoadAndExpectError(ErrorUtils::FormatErrorMessage(
       errors::kRulesFileIsInvalid, keys::kDeclarativeNetRequestKey,
-      keys::kDeclarativeRuleResourcesKey, path2.AsUTF8Unsafe()));
+      keys::kDeclarativeRuleResourcesKey, ruleset_2.relative_file_path));
 }
 
 TEST_F(DNRManifestTest, RulesetCountExceeded) {
-  std::unique_ptr<base::DictionaryValue> manifest =
-      CreateManifest(kJSONRulesFilename);
+  std::vector<TestRulesetInfo> rulesets;
+  for (int i = 0; i <= dnr_api::MAX_NUMBER_OF_STATIC_RULESETS; ++i)
+    rulesets.emplace_back(base::NumberToString(i), base::ListValue());
 
-  ListBuilder rule_resources;
-
-  std::vector<base::FilePath> paths;
-  for (int i = 0; i <= dnr_api::MAX_NUMBER_OF_STATIC_RULESETS; ++i) {
-    base::FilePath path = base::FilePath().AppendASCII(base::NumberToString(i));
-    paths.push_back(path);
-
-    dnr_api::Ruleset ruleset;
-    ruleset.path = path.AsUTF8Unsafe();
-
-    rule_resources.Append(ruleset.ToValue());
-  }
-
-  manifest->SetList(GetRuleResourcesKey(), rule_resources.Build());
-
-  WriteManifestAndRuleset(*manifest, paths);
+  WriteManifestAndRuleset(*CreateManifest(rulesets), rulesets);
 
   LoadAndExpectError(ErrorUtils::FormatErrorMessage(
       errors::kRulesetCountExceeded, keys::kDeclarativeNetRequestKey,
@@ -219,28 +177,24 @@
 }
 
 TEST_F(DNRManifestTest, NonExistentRulesFile) {
-  dnr_api::Ruleset ruleset;
-  ruleset.path = "invalid_file.json";
+  TestRulesetInfo ruleset("invalid_file.json", base::ListValue());
 
-  std::unique_ptr<base::DictionaryValue> manifest =
-      CreateManifest(kJSONRulesFilename);
-  manifest->SetList(GetRuleResourcesKey(),
-                    ListBuilder().Append(ruleset.ToValue()).Build());
+  std::unique_ptr<base::DictionaryValue> manifest = CreateManifest({ruleset});
 
-  WriteManifestAndRuleset(*manifest, {base::FilePath(kJSONRulesetFilepath)});
+  WriteManifestAndRuleset(*manifest, {});
 
   LoadAndExpectError(ErrorUtils::FormatErrorMessage(
       errors::kRulesFileIsInvalid, keys::kDeclarativeNetRequestKey,
-      keys::kDeclarativeRuleResourcesKey, ruleset.path));
+      keys::kDeclarativeRuleResourcesKey, ruleset.relative_file_path));
 }
 
 TEST_F(DNRManifestTest, NeedsDeclarativeNetRequestPermission) {
-  std::unique_ptr<base::DictionaryValue> manifest =
-      CreateManifest(kJSONRulesFilename);
+  std::vector<TestRulesetInfo> rulesets({CreateDefaultRuleset()});
+  std::unique_ptr<base::DictionaryValue> manifest = CreateManifest(rulesets);
   // Remove "declarativeNetRequest" permission.
   manifest->Remove(keys::kPermissions, nullptr);
 
-  WriteManifestAndRuleset(*manifest, {base::FilePath(kJSONRulesetFilepath)});
+  WriteManifestAndRuleset(*manifest, rulesets);
 
   LoadAndExpectError(ErrorUtils::FormatErrorMessage(
       errors::kDeclarativeNetRequestPermissionNeeded, kAPIPermission,
@@ -248,20 +202,13 @@
 }
 
 TEST_F(DNRManifestTest, RulesFileInNestedDirectory) {
-  base::FilePath nested_path =
-      base::FilePath(FILE_PATH_LITERAL("dir")).Append(kJSONRulesetFilepath);
-  std::unique_ptr<base::DictionaryValue> manifest =
-      CreateManifest(kJSONRulesFilename);
+  TestRulesetInfo ruleset("dir/rules_file.json", base::ListValue());
 
-  dnr_api::Ruleset ruleset;
-  ruleset.path = "dir/rules_file.json";
+  std::vector<TestRulesetInfo> rulesets({ruleset});
+  std::unique_ptr<base::DictionaryValue> manifest = CreateManifest(rulesets);
 
-  manifest->SetList(GetRuleResourcesKey(),
-                    ListBuilder().Append(ruleset.ToValue()).Build());
-
-  WriteManifestAndRuleset(*manifest, {nested_path});
-
-  LoadAndExpectSuccess({nested_path});
+  WriteManifestAndRuleset(*manifest, rulesets);
+  LoadAndExpectSuccess(rulesets);
 }
 
 }  // namespace
diff --git a/extensions/common/api/declarative_net_request/test_utils.cc b/extensions/common/api/declarative_net_request/test_utils.cc
index d21a8d5..92f3191 100644
--- a/extensions/common/api/declarative_net_request/test_utils.cc
+++ b/extensions/common/api/declarative_net_request/test_utils.cc
@@ -39,8 +39,12 @@
   return source.ToValue();
 }
 
+std::unique_ptr<base::Value> ToValue(const TestRulesetInfo& info) {
+  return info.GetManifestValue();
+}
+
 template <typename T>
-std::unique_ptr<base::Value> ToValue(const std::vector<T>& vec) {
+std::unique_ptr<base::ListValue> ToValue(const std::vector<T>& vec) {
   ListBuilder builder;
   for (const T& t : vec)
     builder.Append(ToValue(t));
@@ -57,62 +61,6 @@
   dict->Set(key, ToValue(*value));
 }
 
-// Helper to build an extension manifest which uses the
-// kDeclarativeNetRequestKey manifest key. |hosts| specifies the host
-// permissions to grant. |flags| is a bitmask of ConfigFlag to configure the
-// extension. |ruleset_info| specifies the static rulesets for the extension.
-std::unique_ptr<base::DictionaryValue> CreateManifest(
-    const std::vector<TestRulesetInfo>& ruleset_info,
-    const std::vector<std::string>& hosts,
-    unsigned flags) {
-  std::vector<std::string> permissions = hosts;
-  permissions.push_back(kAPIPermission);
-
-  // These permissions are needed for some tests. TODO(karandeepb): Add a
-  // ConfigFlag for these.
-  permissions.push_back("webRequest");
-  permissions.push_back("webRequestBlocking");
-
-  if (flags & kConfig_HasFeedbackPermission)
-    permissions.push_back(kFeedbackAPIPermission);
-
-  if (flags & kConfig_HasActiveTab)
-    permissions.push_back("activeTab");
-
-  std::vector<std::string> background_scripts;
-  if (flags & kConfig_HasBackgroundScript)
-    background_scripts.push_back("background.js");
-
-  ListBuilder rule_resources_builder;
-  for (const TestRulesetInfo& info : ruleset_info) {
-    dnr_api::Ruleset ruleset;
-    ruleset.path = info.relative_file_path;
-    rule_resources_builder.Append(ruleset.ToValue());
-  }
-
-  DictionaryBuilder manifest_builder;
-
-  if (flags & kConfig_OmitDeclarativeNetRequestKey) {
-    DCHECK(ruleset_info.empty());
-  } else {
-    manifest_builder.Set(keys::kDeclarativeNetRequestKey,
-                         DictionaryBuilder()
-                             .Set(keys::kDeclarativeRuleResourcesKey,
-                                  rule_resources_builder.Build())
-                             .Build());
-  }
-
-  return manifest_builder.Set(keys::kName, "Test extension")
-      .Set(keys::kPermissions, ToListValue(permissions))
-      .Set(keys::kVersion, "1.0")
-      .Set(keys::kManifestVersion, 2)
-      .Set("background", DictionaryBuilder()
-                             .Set("scripts", ToListValue(background_scripts))
-                             .Build())
-      .Set(keys::kBrowserAction, DictionaryBuilder().Build())
-      .Build();
-}
-
 }  // namespace
 
 TestRuleCondition::TestRuleCondition() = default;
@@ -239,28 +187,74 @@
   return rule;
 }
 
+TestRulesetInfo::TestRulesetInfo(const std::string& relative_file_path,
+                                 const base::Value& rules_value)
+    : relative_file_path(relative_file_path),
+      rules_value(rules_value.Clone()) {}
+
+TestRulesetInfo::TestRulesetInfo(const TestRulesetInfo& info)
+    : TestRulesetInfo(info.relative_file_path, info.rules_value) {}
+
+std::unique_ptr<base::DictionaryValue> TestRulesetInfo::GetManifestValue()
+    const {
+  dnr_api::Ruleset ruleset;
+  ruleset.path = relative_file_path;
+  return ruleset.ToValue();
+}
+
 std::unique_ptr<base::DictionaryValue> CreateManifest(
-    const std::string& json_rules_filename,
+    const std::vector<TestRulesetInfo>& ruleset_info,
     const std::vector<std::string>& hosts,
     unsigned flags) {
-  std::vector<TestRulesetInfo> rulesets;
-  rulesets.push_back({json_rules_filename, base::ListValue()});
-  return CreateManifest(rulesets, hosts, flags);
+  std::vector<std::string> permissions = hosts;
+  permissions.push_back(kAPIPermission);
+
+  // These permissions are needed for some tests. TODO(karandeepb): Add a
+  // ConfigFlag for these.
+  permissions.push_back("webRequest");
+  permissions.push_back("webRequestBlocking");
+
+  if (flags & kConfig_HasFeedbackPermission)
+    permissions.push_back(kFeedbackAPIPermission);
+
+  if (flags & kConfig_HasActiveTab)
+    permissions.push_back("activeTab");
+
+  std::vector<std::string> background_scripts;
+  if (flags & kConfig_HasBackgroundScript)
+    background_scripts.push_back("background.js");
+
+  DictionaryBuilder manifest_builder;
+
+  if (flags & kConfig_OmitDeclarativeNetRequestKey) {
+    DCHECK(ruleset_info.empty());
+  } else {
+    manifest_builder.Set(
+        keys::kDeclarativeNetRequestKey,
+        DictionaryBuilder()
+            .Set(keys::kDeclarativeRuleResourcesKey, ToValue(ruleset_info))
+            .Build());
+  }
+
+  return manifest_builder.Set(keys::kName, "Test extension")
+      .Set(keys::kPermissions, ToValue(permissions))
+      .Set(keys::kVersion, "1.0")
+      .Set(keys::kManifestVersion, 2)
+      .Set("background", DictionaryBuilder()
+                             .Set("scripts", ToValue(background_scripts))
+                             .Build())
+      .Set(keys::kBrowserAction, DictionaryBuilder().Build())
+      .Build();
 }
 
 std::unique_ptr<base::ListValue> ToListValue(
     const std::vector<std::string>& vec) {
-  ListBuilder builder;
-  for (const std::string& str : vec)
-    builder.Append(str);
-  return builder.Build();
+  return ToValue(vec);
 }
 
-std::unique_ptr<base::ListValue> ToListValue(const std::vector<TestRule>& vec) {
-  ListBuilder builder;
-  for (const TestRule& rule : vec)
-    builder.Append(rule.ToValue());
-  return builder.Build();
+std::unique_ptr<base::ListValue> ToListValue(
+    const std::vector<TestRule>& rules) {
+  return ToValue(rules);
 }
 
 void WriteManifestAndRulesets(const base::FilePath& extension_dir,
@@ -290,9 +284,7 @@
                              const TestRulesetInfo& info,
                              const std::vector<std::string>& hosts,
                              unsigned flags) {
-  std::vector<TestRulesetInfo> rulesets;
-  rulesets.push_back({info.relative_file_path, info.rules_value.Clone()});
-  WriteManifestAndRulesets(extension_dir, rulesets, hosts, flags);
+  WriteManifestAndRulesets(extension_dir, {info}, hosts, flags);
 }
 
 }  // namespace declarative_net_request
diff --git a/extensions/common/api/declarative_net_request/test_utils.h b/extensions/common/api/declarative_net_request/test_utils.h
index 4bae458e..b38e088 100644
--- a/extensions/common/api/declarative_net_request/test_utils.h
+++ b/extensions/common/api/declarative_net_request/test_utils.h
@@ -157,19 +157,28 @@
 
 // Describes a single extension ruleset.
 struct TestRulesetInfo {
+  TestRulesetInfo(const std::string& relative_file_path,
+                  const base::Value& rules_value);
+  TestRulesetInfo(const TestRulesetInfo&);
+  TestRulesetInfo& operator=(const TestRulesetInfo&);
+
   // File path relative to the extension directory.
   std::string relative_file_path;
 
   // The base::Value corresponding to the rules in the ruleset.
   base::Value rules_value;
+
+  // Returns the corresponding value to be specified in the manifest for the
+  // ruleset.
+  std::unique_ptr<base::DictionaryValue> GetManifestValue() const;
 };
 
 // Helper to build an extension manifest which uses the
 // kDeclarativeNetRequestKey manifest key. |hosts| specifies the host
 // permissions to grant. |flags| is a bitmask of ConfigFlag to configure the
-// extension. Should be used when the extension has a single static ruleset.
+// extension. |ruleset_info| specifies the static rulesets for the extension.
 std::unique_ptr<base::DictionaryValue> CreateManifest(
-    const std::string& json_rules_filename,
+    const std::vector<TestRulesetInfo>& ruleset_info,
     const std::vector<std::string>& hosts = {},
     unsigned flags = ConfigFlag::kConfig_None);
 
diff --git a/extensions/common/permissions/permission_message_test_util.cc b/extensions/common/permissions/permission_message_test_util.cc
index d4ff639..d4bccec6 100644
--- a/extensions/common/permissions/permission_message_test_util.cc
+++ b/extensions/common/permissions/permission_message_test_util.cc
@@ -9,6 +9,7 @@
 #include <algorithm>
 #include <iterator>
 
+#include "base/strings/strcat.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -26,23 +27,6 @@
       provider->GetAllPermissionIDs(permissions, extension_type));
 }
 
-std::vector<base::string16> MakeVectorString16(const base::string16& str) {
-  return std::vector<base::string16>(1, str);
-}
-
-std::vector<base::string16> MakeVectorString16(const base::string16& str1,
-                                               const base::string16& str2) {
-  std::vector<base::string16> result;
-  result.push_back(str1);
-  result.push_back(str2);
-  return result;
-}
-
-std::vector<base::string16> MakeVectorString16(const std::string& str1,
-                                               const std::string& str2) {
-  return MakeVectorString16(base::UTF8ToUTF16(str1), base::UTF8ToUTF16(str2));
-}
-
 std::vector<base::string16> MakeVectorString16(
     const std::vector<std::string>& vec) {
   std::vector<base::string16> result;
@@ -52,11 +36,6 @@
 }
 
 std::vector<std::vector<base::string16>> MakeVectorVectorString16(
-    const std::vector<base::string16>& vec) {
-  return std::vector<std::vector<base::string16>>(1, vec);
-}
-
-std::vector<std::vector<base::string16>> MakeVectorVectorString16(
     const std::vector<std::vector<std::string>>& vecs) {
   std::vector<std::vector<base::string16>> result;
   for (const std::vector<std::string>& vec : vecs)
@@ -66,16 +45,17 @@
 
 // Returns the vector of messages concatenated into a single string, separated
 // by newlines, e.g.: "Bar"\n"Baz"\n
-base::string16 MessagesVectorToString(
+std::string MessagesVectorToString(
     const std::vector<base::string16>& messages) {
   if (messages.empty())
-    return base::ASCIIToUTF16("\n");
-  return base::ASCIIToUTF16("\"") +
-         base::JoinString(messages, base::ASCIIToUTF16("\"\n\"")) +
-         base::ASCIIToUTF16("\"\n");
+    return "\n";
+  return base::StrCat({"\"",
+                       base::UTF16ToUTF8(base::JoinString(
+                           messages, base::ASCIIToUTF16("\"\n\""))),
+                       "\"\n"});
 }
 
-base::string16 MessagesToString(const PermissionMessages& messages) {
+std::string MessagesToString(const PermissionMessages& messages) {
   std::vector<base::string16> messages_vec;
   for (const PermissionMessage& msg : messages)
     messages_vec.push_back(msg.message());
@@ -182,33 +162,17 @@
 
 testing::AssertionResult VerifyHasPermissionMessage(
     const PermissionsData* permissions_data,
-    const std::string& expected_message) {
-  return VerifyHasPermissionMessage(permissions_data,
-                                    base::UTF8ToUTF16(expected_message));
-}
-
-testing::AssertionResult VerifyHasPermissionMessage(
-    const PermissionsData* permissions_data,
     const base::string16& expected_message) {
   return VerifyHasPermissionMessageImpl(
-      expected_message, std::vector<base::string16>(),
-      permissions_data->GetPermissionMessages());
+      expected_message, {}, permissions_data->GetPermissionMessages());
 }
 
 testing::AssertionResult VerifyHasPermissionMessage(
     const PermissionSet& permissions,
     Manifest::Type extension_type,
     const std::string& expected_message) {
-  return VerifyHasPermissionMessage(permissions, extension_type,
-                                    base::UTF8ToUTF16(expected_message));
-}
-
-testing::AssertionResult VerifyHasPermissionMessage(
-    const PermissionSet& permissions,
-    Manifest::Type extension_type,
-    const base::string16& expected_message) {
   return VerifyHasPermissionMessageImpl(
-      expected_message, std::vector<base::string16>(),
+      base::UTF8ToUTF16(expected_message), {},
       GetMessages(permissions, extension_type));
 }
 
@@ -228,8 +192,7 @@
 testing::AssertionResult VerifyOnePermissionMessage(
     const PermissionsData* permissions_data,
     const base::string16& expected_message) {
-  return VerifyPermissionMessages(permissions_data,
-                                  MakeVectorString16(expected_message), true);
+  return VerifyPermissionMessages(permissions_data, {expected_message}, true);
 }
 
 testing::AssertionResult VerifyOnePermissionMessage(
@@ -237,8 +200,7 @@
     Manifest::Type extension_type,
     const base::string16& expected_message) {
   return VerifyPermissionMessagesWithSubmessagesImpl(
-      MakeVectorString16(expected_message),
-      std::vector<std::vector<base::string16>>(1),
+      {expected_message}, std::vector<std::vector<base::string16>>(1),
       GetMessages(permissions, extension_type), true);
 }
 
@@ -246,18 +208,8 @@
     const PermissionsData* permissions_data,
     const std::string& expected_message,
     const std::vector<std::string>& expected_submessages) {
-  return VerifyOnePermissionMessageWithSubmessages(
-      permissions_data, base::UTF8ToUTF16(expected_message),
-      MakeVectorString16(expected_submessages));
-}
-
-testing::AssertionResult VerifyOnePermissionMessageWithSubmessages(
-    const PermissionsData* permissions_data,
-    const base::string16& expected_message,
-    const std::vector<base::string16>& expected_submessages) {
   return VerifyPermissionMessagesWithSubmessages(
-      permissions_data, MakeVectorString16(expected_message),
-      MakeVectorVectorString16(expected_submessages), true);
+      permissions_data, {expected_message}, {expected_submessages}, true);
 }
 
 testing::AssertionResult VerifyTwoPermissionMessages(
@@ -265,19 +217,10 @@
     const std::string& expected_message_1,
     const std::string& expected_message_2,
     bool check_order) {
-  return VerifyPermissionMessages(
-      permissions_data,
-      MakeVectorString16(expected_message_1, expected_message_2), check_order);
-}
-
-testing::AssertionResult VerifyTwoPermissionMessages(
-    const PermissionsData* permissions_data,
-    const base::string16& expected_message_1,
-    const base::string16& expected_message_2,
-    bool check_order) {
-  return VerifyPermissionMessages(
-      permissions_data,
-      MakeVectorString16(expected_message_1, expected_message_2), check_order);
+  return VerifyPermissionMessages(permissions_data,
+                                  {base::UTF8ToUTF16(expected_message_1),
+                                   base::UTF8ToUTF16(expected_message_2)},
+                                  check_order);
 }
 
 testing::AssertionResult VerifyPermissionMessages(
diff --git a/extensions/common/permissions/permission_message_test_util.h b/extensions/common/permissions/permission_message_test_util.h
index 34e36f3..63859773 100644
--- a/extensions/common/permissions/permission_message_test_util.h
+++ b/extensions/common/permissions/permission_message_test_util.h
@@ -19,18 +19,11 @@
 
 testing::AssertionResult VerifyHasPermissionMessage(
     const PermissionsData* permissions_data,
-    const std::string& expected_message);
-testing::AssertionResult VerifyHasPermissionMessage(
-    const PermissionsData* permissions_data,
     const base::string16& expected_message);
 testing::AssertionResult VerifyHasPermissionMessage(
     const PermissionSet& permissions,
     Manifest::Type extension_type,
     const std::string& expected_message);
-testing::AssertionResult VerifyHasPermissionMessage(
-    const PermissionSet& permissions,
-    Manifest::Type extension_type,
-    const base::string16& expected_message);
 
 testing::AssertionResult VerifyNoPermissionMessages(
     const PermissionsData* permissions_data);
@@ -50,21 +43,12 @@
     const PermissionsData* permissions_data,
     const std::string& expected_message,
     const std::vector<std::string>& expected_submessages);
-testing::AssertionResult VerifyOnePermissionMessageWithSubmessages(
-    const PermissionsData* permissions_data,
-    const base::string16& expected_message,
-    const std::vector<base::string16>& expected_submessages);
 
 testing::AssertionResult VerifyTwoPermissionMessages(
     const PermissionsData* permissions_data,
     const std::string& expected_message_1,
     const std::string& expected_message_2,
     bool check_order);
-testing::AssertionResult VerifyTwoPermissionMessages(
-    const PermissionsData* permissions_data,
-    const base::string16& expected_message_1,
-    const base::string16& expected_message_2,
-    bool check_order);
 
 testing::AssertionResult VerifyPermissionMessages(
     const PermissionsData* permissions_data,
diff --git a/extensions/renderer/resources/set_icon.js b/extensions/renderer/resources/set_icon.js
index fb023dd1..86fa5ef 100644
--- a/extensions/renderer/resources/set_icon.js
+++ b/extensions/renderer/resources/set_icon.js
@@ -2,27 +2,68 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+var exceptionHandler = require('uncaught_exception_handler');
 var SetIconCommon = requireNative('setIcon').SetIconCommon;
 
-function loadImagePath(path, callback) {
+var inServiceWorker = 'ServiceWorkerGlobalScope' in self;
+
+function loadImagePathForServiceWorker(path, callback, failureCallback) {
+  let fetchPromise = fetch(path);
+
+  let blobPromise = $Promise.then(fetchPromise, (response) => {
+    if (!response.ok) {
+      throw $Error.self('Could not fetch action icon \'' + path + '\'.');
+    }
+    return response.blob();
+  });
+
+  let imagePromise = $Promise.then(blobPromise, (blob) => {
+    return createImageBitmap(blob);
+  });
+
+  let imageDataPromise = $Promise.then(imagePromise, (image) => {
+    var canvas = new OffscreenCanvas(image.width, image.height);
+    var canvasContext = canvas.getContext('2d');
+    canvasContext.clearRect(0, 0, canvas.width, canvas.height);
+    canvasContext.drawImage(image, 0, 0, canvas.width, canvas.height);
+    var imageData = canvasContext.getImageData(0, 0, canvas.width,
+                                               canvas.height);
+    callback(imageData);
+  });
+
+  $Promise.catch(imageDataPromise, function(error) {
+    failureCallback(exceptionHandler.safeErrorToString(error, true));
+  });
+}
+
+function loadImagePathForNonServiceWorker(path, callback, failureCallback) {
   var img = new Image();
   img.onerror = function() {
-    console.error('Could not load action icon \'' + path + '\'.');
+    var message = 'Could not load action icon \'' + path + '\'.';
+    console.error(message);
   };
   img.onload = function() {
     var canvas = document.createElement('canvas');
     canvas.width = img.width;
     canvas.height = img.height
-    var canvas_context = canvas.getContext('2d');
-    canvas_context.clearRect(0, 0, canvas.width, canvas.height);
-    canvas_context.drawImage(img, 0, 0, canvas.width, canvas.height);
-    var imageData = canvas_context.getImageData(0, 0, canvas.width,
-                                                canvas.height);
+    var canvasContext = canvas.getContext('2d');
+    canvasContext.clearRect(0, 0, canvas.width, canvas.height);
+    canvasContext.drawImage(img, 0, 0, canvas.width, canvas.height);
+    var imageData = canvasContext.getImageData(0, 0, canvas.width,
+                                               canvas.height);
     callback(imageData);
   };
   img.src = path;
 }
 
+function loadImagePath(path, callback, failureCallback) {
+  if (inServiceWorker) {
+    loadImagePathForServiceWorker(path, callback, failureCallback);
+  } else {
+    loadImagePathForNonServiceWorker(path, callback, failureCallback);
+  }
+}
+
 function smellsLikeImageData(imageData) {
   // See if this object at least looks like an ImageData element.
   // Unfortunately, we cannot use instanceof because the ImageData
@@ -51,8 +92,10 @@
  * @param {Function} callback
  *   The callback function to pass processed imageData back to. Note that this
  *   callback may be called reentrantly.
+ * @param {Function} failureCallback
+ *   The callback function to be called in case of an error.
  */
-function setIcon(details, callback) {
+function setIcon(details, callback, failureCallback) {
   // Note that iconIndex is actually deprecated, and only available to the
   // pageAction API.
   // TODO(kalman): Investigate whether this is for the pageActions API, and if
@@ -90,7 +133,7 @@
           details.imageData[size] = imageData;
           if (--detailKeyCount == 0)
             callback(SetIconCommon(details));
-        }.bind(null, iconSize));
+        }.bind(null, iconSize), failureCallback);
       }
       if (detailKeyCount == 0)
         throw new Error('The path property must not be empty.');
@@ -100,7 +143,7 @@
         details.imageData[imageData.width.toString()] = imageData;
         delete details.path;
         callback(SetIconCommon(details));
-      });
+      }, failureCallback);
     }
     return;
   }
diff --git a/fuchsia/base/context_provider_test_connector.cc b/fuchsia/base/context_provider_test_connector.cc
index 28d6d2ee..a438b1de 100644
--- a/fuchsia/base/context_provider_test_connector.cc
+++ b/fuchsia/base/context_provider_test_connector.cc
@@ -20,7 +20,7 @@
 
 namespace cr_fuchsia {
 
-fidl::InterfaceHandle<fuchsia::io::Directory> StartWebEngineForTests(
+fuchsia::web::ContextProviderPtr ConnectContextProvider(
     fidl::InterfaceRequest<fuchsia::sys::ComponentController>
         component_controller_request,
     const base::CommandLine& command_line) {
@@ -49,16 +49,12 @@
   launcher->CreateComponent(std::move(launch_info),
                             std::move(component_controller_request));
 
-  return web_engine_services_dir;
-}
+  sys::ServiceDirectory web_engine_service_dir(
+      std::move(web_engine_services_dir));
 
-fuchsia::web::ContextProviderPtr ConnectContextProvider(
-    fidl::InterfaceRequest<fuchsia::sys::ComponentController>
-        component_controller_request,
-    const base::CommandLine& command_line) {
-  sys::ServiceDirectory web_engine_service_dir(StartWebEngineForTests(
-      std::move(component_controller_request), command_line));
-  return web_engine_service_dir.Connect<fuchsia::web::ContextProvider>();
+  fuchsia::web::ContextProviderPtr context_provider;
+  web_engine_service_dir.Connect(context_provider.NewRequest());
+  return context_provider;
 }
 
 }  // namespace cr_fuchsia
diff --git a/fuchsia/base/context_provider_test_connector.h b/fuchsia/base/context_provider_test_connector.h
index 0d5ca1fd..632c6f9 100644
--- a/fuchsia/base/context_provider_test_connector.h
+++ b/fuchsia/base/context_provider_test_connector.h
@@ -8,18 +8,11 @@
 #include <fuchsia/sys/cpp/fidl.h>
 #include <fuchsia/web/cpp/fidl.h>
 #include <lib/fidl/cpp/interface_request.h>
-#include <lib/sys/cpp/service_directory.h>
 
 #include "base/command_line.h"
 
 namespace cr_fuchsia {
 
-fidl::InterfaceHandle<fuchsia::io::Directory> StartWebEngineForTests(
-    fidl::InterfaceRequest<fuchsia::sys::ComponentController>
-        component_controller_request,
-    const base::CommandLine& command_line =
-        base::CommandLine(base::CommandLine::NO_PROGRAM));
-
 // TODO(crbug.com/1046615): Use test manifests for package specification.
 fuchsia::web::ContextProviderPtr ConnectContextProvider(
     fidl::InterfaceRequest<fuchsia::sys::ComponentController>
diff --git a/fuchsia/engine/DEPS b/fuchsia/engine/DEPS
index 8cf4a1f5..ece5057 100644
--- a/fuchsia/engine/DEPS
+++ b/fuchsia/engine/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+cc/base/switches.h",
   "+components/version_info",
   "+components/viz/common",
   "+content/public/app",
diff --git a/fuchsia/engine/browser/web_engine_content_browser_client.cc b/fuchsia/engine/browser/web_engine_content_browser_client.cc
index 15768cd..b1cc726 100644
--- a/fuchsia/engine/browser/web_engine_content_browser_client.cc
+++ b/fuchsia/engine/browser/web_engine_content_browser_client.cc
@@ -147,7 +147,6 @@
   constexpr char const* kSwitchesToCopy[] = {
       switches::kContentDirectories,
       switches::kDisableSoftwareVideoDecoders,
-      switches::kEnableFuchsiaAudioConsumer,
       switches::kEnableProtectedVideoBuffers,
       switches::kEnableWidevine,
       switches::kForceProtectedVideoOutputBuffers,
diff --git a/fuchsia/engine/context_provider_impl.cc b/fuchsia/engine/context_provider_impl.cc
index 313451d1..514c4ae 100644
--- a/fuchsia/engine/context_provider_impl.cc
+++ b/fuchsia/engine/context_provider_impl.cc
@@ -44,6 +44,7 @@
 #include "base/strings/string_util.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "cc/base/switches.h"
 #include "components/viz/common/features.h"
 #include "content/public/common/content_switches.h"
 #include "fuchsia/base/config_reader.h"
@@ -146,13 +147,13 @@
     return true;
 
   static const base::StringPiece kAllowedArgs[] = {
+      cc::switches::kEnableGpuBenchmarking,
       switches::kAcceleratedCanvas2dMSAASampleCount,
       // TODO(crbug.com/1054589): Remove the "blink-settings" argument.
       switches::kBlinkSettings,
       switches::kDisableFeatures,
       switches::kDisableGpuWatchdog,
       switches::kEnableFeatures,
-      switches::kEnableFuchsiaAudioConsumer,
       switches::kEnableLowEndDeviceMode,
       switches::kForceGpuMemAvailableMb,
       switches::kForceGpuMemDiscardableLimitMb,
@@ -169,14 +170,17 @@
       // experimenting with memory-related command-line options.
       continue;
     }
-    if (!arg.second.is_string()) {
+
+    DCHECK(!command_line->HasSwitch(arg.first));
+    if (arg.second.is_none()) {
+      command_line->AppendSwitch(arg.first);
+    } else if (arg.second.is_string()) {
+      command_line->AppendSwitchNative(arg.first, arg.second.GetString());
+    } else {
       LOG(ERROR) << "Config command-line arg must be a string: " << arg.first;
       return false;
     }
 
-    DCHECK(!command_line->HasSwitch(arg.first));
-    command_line->AppendSwitchNative(arg.first, arg.second.GetString());
-
     // TODO(https://crbug.com/1023012): enable-low-end-device-mode currently
     // fakes 512MB total physical memory, which triggers RGB4444 textures,
     // which
diff --git a/fuchsia/engine/web_engine_integration_test.cc b/fuchsia/engine/web_engine_integration_test.cc
index 819937b..0eae63e 100644
--- a/fuchsia/engine/web_engine_integration_test.cc
+++ b/fuchsia/engine/web_engine_integration_test.cc
@@ -408,9 +408,7 @@
 }
 
 TEST_F(WebEngineIntegrationTest, PlayAudio) {
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  command_line.AppendSwitch(switches::kEnableFuchsiaAudioConsumer);
-  StartWebEngine(std::move(command_line));
+  StartWebEngine();
 
   // Use a FilteredServiceDirectory in order to inject a fake AudioConsumer
   // service.
diff --git a/fuchsia/runners/cast/cast_component.cc b/fuchsia/runners/cast/cast_component.cc
index 69b5c49..95fa1a2 100644
--- a/fuchsia/runners/cast/cast_component.cc
+++ b/fuchsia/runners/cast/cast_component.cc
@@ -156,4 +156,7 @@
   DCHECK(runner()->is_headless());
 
   frame()->DisableHeadlessRendering();
+
+  if (on_headless_disconnect_cb_)
+    std::move(on_headless_disconnect_cb_).Run();
 }
diff --git a/fuchsia/runners/cast/cast_component.h b/fuchsia/runners/cast/cast_component.h
index d6494b6..071970b 100644
--- a/fuchsia/runners/cast/cast_component.h
+++ b/fuchsia/runners/cast/cast_component.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/fuchsia/startup_context.h"
+#include "base/gtest_prod_util.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/message_loop/message_pump_fuchsia.h"
 #include "base/optional.h"
@@ -57,6 +58,13 @@
   // WebComponent overrides.
   void StartComponent() final;
 
+  // Sets a callback that will be invoked when the handle controlling the
+  // lifetime of a headless "view" is dropped.
+  void set_on_headless_disconnect_for_test(
+      base::OnceClosure on_headless_disconnect_cb) {
+    on_headless_disconnect_cb_ = std::move(on_headless_disconnect_cb);
+  }
+
   const chromium::cast::ApplicationConfig& application_config() {
     return application_config_;
   }
@@ -66,6 +74,8 @@
   CastRunner* runner() const;
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(HeadlessCastRunnerIntegrationTest, Headless);
+
   void OnRewriteRulesReceived(
       std::vector<fuchsia::web::UrlRequestRewriteRule> rewrite_rules);
 
@@ -103,6 +113,8 @@
   zx::eventpair headless_view_token_;
   base::MessagePumpForIO::ZxHandleWatchController headless_disconnect_watch_;
 
+  base::OnceClosure on_headless_disconnect_cb_;
+
   fidl::Binding<fuchsia::web::NavigationEventListener>
       navigation_listener_binding_;
 
diff --git a/fuchsia/runners/cast/cast_runner.cc b/fuchsia/runners/cast/cast_runner.cc
index 4c4a274e..baa6cd1b 100644
--- a/fuchsia/runners/cast/cast_runner.cc
+++ b/fuchsia/runners/cast/cast_runner.cc
@@ -117,13 +117,24 @@
 
 CastRunner::CastRunner(
     WebContentRunner::GetContextParamsCallback get_context_params_callback,
-    bool is_headless)
+    bool is_headless,
+    sys::OutgoingDirectory* outgoing_directory)
     : WebContentRunner(base::BindRepeating(&CastRunner::GetMainContextParams,
-                                           base::Unretained(this))),
+                                           base::Unretained(this)),
+                       outgoing_directory),
       get_context_params_callback_(std::move(get_context_params_callback)),
       is_headless_(is_headless),
+      common_create_context_params_(BuildCreateContextParamsForIsolatedRunners(
+          get_context_params_callback_.Run())),
       service_directory_(CreateServiceDirectory()) {}
 
+CastRunner::CastRunner(OnDestructionCallback on_destruction_callback,
+                       fuchsia::web::ContextPtr context,
+                       bool is_headless)
+    : WebContentRunner(std::move(context)),
+      is_headless_(is_headless),
+      on_destruction_callback_(std::move(on_destruction_callback)) {}
+
 CastRunner::~CastRunner() = default;
 
 void CastRunner::StartComponent(
@@ -201,6 +212,10 @@
   pending_components_.emplace(std::move(pending_component_params));
 }
 
+size_t CastRunner::GetChildCastRunnerCountForTest() {
+  return isolated_runners_.size();
+}
+
 void CastRunner::DestroyComponent(WebComponent* component) {
   WebContentRunner::DestroyComponent(component);
 
@@ -355,12 +370,16 @@
 
 CastRunner* CastRunner::CreateChildRunnerForIsolatedComponent(
     CastComponent::CastComponentParams* component_params) {
-  // Construct the CreateContextParams in order to create a new Context.  Some
-  // common parameters must be inherited from default params returned from
-  // |get_context_params_callback_|.
-  fuchsia::web::CreateContextParams isolated_context_params =
-      BuildCreateContextParamsForIsolatedRunners(
-          get_context_params_callback_.Run());
+  // Construct the CreateContextParams in order to create a new Context.
+  // Some common parameters must be inherited from
+  // |common_create_context_params_|.
+  fuchsia::web::CreateContextParams isolated_context_params;
+  zx_status_t status =
+      common_create_context_params_.Clone(&isolated_context_params);
+  if (status != ZX_OK) {
+    ZX_LOG(ERROR, status) << "clone";
+    return nullptr;
+  }
 
   // Service redirection is not necessary for isolated context. Pass default
   // /svc as is, without overriding any services.
@@ -372,16 +391,17 @@
       std::move(*component_params->app_config
                      .mutable_content_directories_for_isolated_application()));
 
-  auto create_context_params_callback = base::BindRepeating(
-      [](fuchsia::web::CreateContextParams isolated_context_params) {
-        return isolated_context_params;
-      },
-      base::Passed(std::move(isolated_context_params)));
+  std::unique_ptr<CastRunner> cast_runner(new CastRunner(
+      base::BindOnce(&CastRunner::OnChildRunnerDestroyed,
+                     base::Unretained(this)),
+      CreateWebContext(std::move(isolated_context_params)), is_headless()));
 
-  auto cast_runner = std::make_unique<CastRunner>(
-      std::move(create_context_params_callback), is_headless());
-  cast_runner->on_destruction_callback_ = base::BindOnce(
-      &CastRunner::OnChildRunnerDestroyed, base::Unretained(this));
+  // If test code is listening for Component creation events, then wire up the
+  // isolated CastRunner to signal component creation events.
+  if (web_component_created_callback_for_test()) {
+    cast_runner->SetWebComponentCreatedCallbackForTest(
+        web_component_created_callback_for_test());
+  }
 
   CastRunner* cast_runner_ptr = cast_runner.get();
   isolated_runners_.insert(std::move(cast_runner));
diff --git a/fuchsia/runners/cast/cast_runner.h b/fuchsia/runners/cast/cast_runner.h
index e9e5637..34e244c9 100644
--- a/fuchsia/runners/cast/cast_runner.h
+++ b/fuchsia/runners/cast/cast_runner.h
@@ -29,17 +29,16 @@
 // sys::Runner which instantiates Cast activities specified via cast/casts URIs.
 class CastRunner : public WebContentRunner {
  public:
-  using OnDestructionCallback = base::OnceCallback<void(CastRunner*)>;
-
-  static constexpr uint16_t kRemoteDebuggingPort = 9222;
-
   // Creates a Runner for Cast components and publishes it into the specified
   // OutgoingDirectory.
   // |get_context_params_callback|: Returns the context parameters to use.
   // |is_headless|: True if |get_context_params_callback| sets the HEADLESS
   //     feature flag.
+  // |outgoing_directory|: The directory that this CastRunner will publish
+  //     itself to.
   CastRunner(GetContextParamsCallback get_context_params_callback,
-             bool is_headless);
+             bool is_headless,
+             sys::OutgoingDirectory* outgoing_directory);
   ~CastRunner() override;
 
   CastRunner(const CastRunner&) = delete;
@@ -60,7 +59,20 @@
   // Returns true if this Runner is configured not to use Scenic.
   bool is_headless() const { return is_headless_; }
 
+  // Returns the number of active CastRunner instances.
+  size_t GetChildCastRunnerCountForTest();
+
  private:
+  using OnDestructionCallback = base::OnceCallback<void(CastRunner*)>;
+
+  // Constructor used for creating CastRunners that run apps in dedicated
+  // Contexts. Child CastRunners may only spawn one Component and will be
+  // destroyed by their parents when their singleton Components are destroyed.
+  // |on_destruction_callback| is invoked when the child component is destroyed.
+  CastRunner(OnDestructionCallback on_destruction_callback,
+             fuchsia::web::ContextPtr context,
+             bool is_headless);
+
   // Creates and returns the service directory that is passed to the main web
   // context.
   std::unique_ptr<base::fuchsia::FilteredServiceDirectory>
@@ -104,6 +116,9 @@
                  base::UniquePtrComparator>
       pending_components_;
 
+  // Used as a template for creating the ContextPtrs of isolated Runners.
+  fuchsia::web::CreateContextParams common_create_context_params_;
+
   // Invoked upon destruction of "isolated" runners, used to signal termination
   // to parents.
   OnDestructionCallback on_destruction_callback_;
diff --git a/fuchsia/runners/cast/cast_runner_integration_test.cc b/fuchsia/runners/cast/cast_runner_integration_test.cc
index c6bb614..69b1dda 100644
--- a/fuchsia/runners/cast/cast_runner_integration_test.cc
+++ b/fuchsia/runners/cast/cast_runner_integration_test.cc
@@ -8,17 +8,13 @@
 #include <lib/sys/cpp/component_context.h>
 #include <lib/ui/scenic/cpp/view_token_pair.h>
 #include <lib/zx/channel.h>
-#include <zircon/processargs.h>
 
 #include "base/base_paths_fuchsia.h"
 #include "base/callback_helpers.h"
 #include "base/fuchsia/file_utils.h"
-#include "base/fuchsia/filtered_service_directory.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/fuchsia/scoped_service_binding.h"
-#include "base/fuchsia/test_component_context_for_process.h"
 #include "base/path_service.h"
-#include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/task_environment.h"
@@ -30,7 +26,6 @@
 #include "fuchsia/base/frame_test_util.h"
 #include "fuchsia/base/fuchsia_dir_scheme.h"
 #include "fuchsia/base/mem_buffer_util.h"
-#include "fuchsia/base/release_channel.h"
 #include "fuchsia/base/result_receiver.h"
 #include "fuchsia/base/string_util.h"
 #include "fuchsia/base/test_devtools_list_fetcher.h"
@@ -39,8 +34,11 @@
 #include "fuchsia/runners/cast/cast_runner.h"
 #include "fuchsia/runners/cast/fake_application_config_manager.h"
 #include "fuchsia/runners/cast/test_api_bindings.h"
+#include "fuchsia/runners/common/web_component.h"
+#include "fuchsia/runners/common/web_content_runner.h"
 #include "net/test/embedded_test_server/default_handlers.h"
 #include "net/test/embedded_test_server/http_request.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -49,6 +47,7 @@
 
 constexpr char kBlankAppUrl[] = "/defaultresponse";
 constexpr char kEchoHeaderPath[] = "/echoheader?Test";
+constexpr char kEchoAppPath[] = "/echo.html";
 
 constexpr char kTestServerRoot[] =
     FILE_PATH_LITERAL("fuchsia/runners/cast/testdata");
@@ -56,6 +55,10 @@
 constexpr char kDummyAgentUrl[] =
     "fuchsia-pkg://fuchsia.com/dummy_agent#meta/dummy_agent.cmx";
 
+void ComponentErrorHandler(zx_status_t status) {
+  ZX_LOG(ERROR, status) << "Component launch failed";
+  ADD_FAILURE();
+}
 
 // Helper used to ensure that cr_fuchsia::RegisterFuchsiaDirScheme() is called
 // once per process to register fuchsia-dir scheme. In cast_runner this function
@@ -91,8 +94,7 @@
     rules_sent_ = true;
 
     std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
-    rewrites.push_back(
-        cr_fuchsia::CreateRewriteAddHeaders("Test", "TestHeaderValue"));
+    rewrites.push_back(cr_fuchsia::CreateRewriteAddHeaders("Test", "Value"));
     fuchsia::web::UrlRequestRewriteRule rule;
     rule.set_rewrites(std::move(rewrites));
     std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
@@ -195,37 +197,31 @@
       context_binding_;
   base::OnceClosure on_delete_;
 };
+
 }  // namespace
 
 class CastRunnerIntegrationTest : public testing::Test {
  public:
-  CastRunnerIntegrationTest() : CastRunnerIntegrationTest(/*headless=*/false) {}
+  CastRunnerIntegrationTest()
+      : CastRunnerIntegrationTest(fuchsia::web::ContextFeatureFlags::NETWORK) {}
   CastRunnerIntegrationTest(const CastRunnerIntegrationTest&) = delete;
   CastRunnerIntegrationTest& operator=(const CastRunnerIntegrationTest&) =
       delete;
 
   void TearDown() override {
-    if (component_controller_)
-      ShutdownComponent();
-
     // Disconnect the CastRunner & let things tear-down.
     cast_runner_ptr_.Unbind();
     base::RunLoop().RunUntilIdle();
   }
 
  protected:
-  explicit CastRunnerIntegrationTest(bool headless)
+  explicit CastRunnerIntegrationTest(
+      fuchsia::web::ContextFeatureFlags feature_flags)
       : app_config_manager_binding_(&component_services_,
                                     &app_config_manager_) {
     EnsureFuchsiaDirSchemeInitialized();
 
     // Create the CastRunner, published into |outgoing_directory_|.
-    fuchsia::web::ContextFeatureFlags feature_flags =
-        fuchsia::web::ContextFeatureFlags::NETWORK;
-    if (headless) {
-      feature_flags =
-          feature_flags | fuchsia::web::ContextFeatureFlags::HEADLESS;
-    }
     WebContentRunner::GetContextParamsCallback get_context_params =
         base::BindLambdaForTesting([feature_flags]() {
           fuchsia::web::CreateContextParams create_context_params;
@@ -235,15 +231,19 @@
                   base::FilePath(base::fuchsia::kServiceDirectoryPath)));
           CHECK(create_context_params.service_directory());
 
+          const uint16_t kRemoteDebuggingAnyPort = 0;
           create_context_params.set_remote_debugging_port(
-              CastRunner::kRemoteDebuggingPort);
+              kRemoteDebuggingAnyPort);
           return create_context_params;
         });
-    cast_runner_ =
-        std::make_unique<CastRunner>(std::move(get_context_params), headless);
-    cast_runner_->PublishRunnerService(&outgoing_directory_);
+    cast_runner_ = std::make_unique<CastRunner>(
+        std::move(get_context_params),
+        (feature_flags & fuchsia::web::ContextFeatureFlags::HEADLESS) ==
+            fuchsia::web::ContextFeatureFlags::HEADLESS,
+        &outgoing_directory_);
 
-    StartAndPublishWebEngine();
+    cast_runner_->SetContextProviderForTest(cr_fuchsia::ConnectContextProvider(
+        context_provider_controller_.NewRequest()));
 
     // Connect to the CastRunner's fuchsia.sys.Runner interface.
     fidl::InterfaceHandle<fuchsia::io::Directory> directory;
@@ -260,24 +260,6 @@
     test_server_.ServeFilesFromSourceDirectory(kTestServerRoot);
     net::test_server::RegisterDefaultHandlers(&test_server_);
     EXPECT_TRUE(test_server_.Start());
-
-    // Inject ApiBinding that used by ExecuteJavaScript().
-    std::vector<chromium::cast::ApiBinding> binding_list;
-    chromium::cast::ApiBinding eval_js_binding;
-    eval_js_binding.set_before_load_script(cr_fuchsia::MemBufferFromString(
-        "window.addEventListener('DOMContentLoaded', (event) => {"
-        "  var port = cast.__platform__.PortConnector.bind('testport');"
-        "  port.onmessage = (e) => {"
-        "    var result = eval(e.data);"
-        "    if (typeof(result) == \"undefined\") {"
-        "      result = \"undefined\";"
-        "    }"
-        "    port.postMessage(result);"
-        "  };"
-        "});",
-        "test"));
-    binding_list.emplace_back(std::move(eval_js_binding));
-    api_bindings_.set_bindings(std::move(binding_list));
   }
 
   std::unique_ptr<cr_fuchsia::AgentImpl::ComponentStateBase> OnComponentConnect(
@@ -287,31 +269,12 @@
         url_request_rewrite_rules_provider_.get());
     component_state_ = component_state.get();
 
-    if (component_state_created_callback_)
-      std::move(component_state_created_callback_).Run();
+    if (init_component_state_callback_)
+      std::move(init_component_state_callback_).Run(component_state_);
 
     return component_state;
   }
 
-  void StartAndPublishWebEngine() {
-    fidl::InterfaceHandle<fuchsia::io::Directory> web_engine_outgoing_dir =
-        cr_fuchsia::StartWebEngineForTests(web_engine_controller_.NewRequest());
-    sys::ServiceDirectory web_engine_outgoing_services(
-        std::move(web_engine_outgoing_dir));
-
-    test_component_context_.additional_services()
-        ->RemovePublicService<fuchsia::web::ContextProvider>();
-    test_component_context_.additional_services()->AddPublicService(
-        std::make_unique<vfs::Service>(
-            [web_engine_outgoing_services =
-                 std::move(web_engine_outgoing_services)](
-                zx::channel channel, async_dispatcher_t* dispatcher) {
-              web_engine_outgoing_services.Connect(
-                  fuchsia::web::ContextProvider::Name_, std::move(channel));
-            }),
-        fuchsia::web::ContextProvider::Name_);
-  }
-
   void RegisterAppWithTestData(GURL url) {
     fuchsia::web::ContentDirectoryProvider provider;
     provider.set_name("testdata");
@@ -333,8 +296,7 @@
     auto component_url = base::StringPrintf("cast:%s", kTestAppId);
     CreateComponentContext(component_url);
     StartCastComponent(component_url);
-    WaitComponentState();
-    WaitTestPort();
+    WaitComponentCreated();
   }
 
   void CreateComponentContext(const base::StringPiece& component_url) {
@@ -360,7 +322,7 @@
     startup_info.launch_info.directory_request =
         outgoing_directory.NewRequest().TakeChannel();
 
-    fidl::InterfaceHandle<fuchsia::io::Directory> svc_directory;
+    fidl::InterfaceHandle<::fuchsia::io::Directory> svc_directory;
     CHECK_EQ(fdio_service_connect_at(
                  outgoing_directory.channel().get(), "svc",
                  svc_directory.NewRequest().TakeChannel().release()),
@@ -378,67 +340,40 @@
     fuchsia::sys::Package package;
     package.resolved_url = component_url.as_string();
 
-    cast_runner_->StartComponent(std::move(package), std::move(startup_info),
-                                 component_controller_.NewRequest());
-    component_controller_.set_error_handler([](zx_status_t status) {
-      ZX_LOG(ERROR, status) << "Component launch failed";
-      ADD_FAILURE();
-    });
+    cast_runner_ptr_->StartComponent(std::move(package),
+                                     std::move(startup_info),
+                                     component_controller_.NewRequest());
+    component_controller_.set_error_handler(&ComponentErrorHandler);
   }
 
-  // Executes |code| in the context of the test application and the returns
-  // serialized as string.
-  std::string ExecuteJavaScript(const std::string& code) {
-    fuchsia::web::WebMessage message;
-    message.set_data(cr_fuchsia::MemBufferFromString(code, "test-msg"));
-    test_port_->PostMessage(
-        std::move(message),
-        [](fuchsia::web::MessagePort_PostMessage_Result result) {
-          EXPECT_TRUE(result.is_response());
-        });
-
-    base::RunLoop response_loop;
-    cr_fuchsia::ResultReceiver<fuchsia::web::WebMessage> response(
-        response_loop.QuitClosure());
-    test_port_->ReceiveMessage(
-        cr_fuchsia::CallbackToFitFunction(response.GetReceiveCallback()));
-    response_loop.Run();
-
-    std::string response_string;
-    EXPECT_TRUE(
-        cr_fuchsia::StringFromMemBuffer(response->data(), &response_string));
-
-    return response_string;
-  }
-
-  void WaitComponentState() {
-    base::RunLoop run_loop;
-    component_state_created_callback_ = run_loop.QuitClosure();
-    run_loop.Run();
-  }
-
-  void WaitTestPort() {
-    CHECK(!test_port_);
-    test_port_ = api_bindings_.RunUntilMessagePortReceived("testport").Bind();
-  }
-
-  void CheckAppUrl(const GURL& app_url) {
-    EXPECT_EQ(ExecuteJavaScript("window.location.href"), app_url.spec());
-  }
-
-  void ShutdownComponent() {
-    DCHECK(component_controller_);
+  void WaitComponentCreated() {
+    ASSERT_FALSE(cast_component_);
 
     base::RunLoop run_loop;
-    component_state_->set_on_delete(run_loop.QuitClosure());
-    component_controller_.Unbind();
+    cr_fuchsia::ResultReceiver<WebComponent*> component_receiver(
+        run_loop.QuitClosure());
+    cast_runner_->SetWebComponentCreatedCallbackForTest(
+        base::AdaptCallbackForRepeating(
+            component_receiver.GetReceiveCallback()));
     run_loop.Run();
+    ASSERT_NE(*component_receiver, nullptr);
+    cast_component_ = reinterpret_cast<CastComponent*>(*component_receiver);
+  }
 
-    component_controller_ = nullptr;
+  void WaitUrlAndTitle(const GURL& url, const std::string& title) {
+    base::RunLoop run_loop;
+    cr_fuchsia::TestNavigationListener listener;
+    fidl::Binding<fuchsia::web::NavigationEventListener> listener_binding(
+        &listener);
+    cast_component_->frame()->SetNavigationEventListener(
+        listener_binding.NewBinding());
+    listener.RunUntilUrlAndTitleEquals(url, title);
   }
 
   void WaitForComponentDestroyed() {
+    ASSERT_TRUE(cast_component_);
     ASSERT_TRUE(component_state_);
+
     base::RunLoop state_loop;
     component_state_->set_on_delete(state_loop.QuitClosure());
 
@@ -457,14 +392,13 @@
     component_context_ = nullptr;
     component_services_client_ = nullptr;
     component_state_ = nullptr;
+    cast_component_ = nullptr;
   }
 
   base::test::SingleThreadTaskEnvironment task_environment_{
       base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
   net::EmbeddedTestServer test_server_;
 
-  fuchsia::sys::ComponentControllerPtr web_engine_controller_;
-
   FakeApplicationConfigManager app_config_manager_;
   TestApiBindings api_bindings_;
   std::unique_ptr<FakeUrlRequestRewriteRulesProvider>
@@ -478,17 +412,16 @@
   fuchsia::sys::ComponentControllerPtr component_controller_;
   std::unique_ptr<sys::ServiceDirectory> component_services_client_;
   FakeComponentState* component_state_ = nullptr;
-  fuchsia::web::MessagePortPtr test_port_;
+  CastComponent* cast_component_ = nullptr;
 
-  base::OnceClosure component_state_created_callback_;
+  base::OnceCallback<void(FakeComponentState*)> init_component_state_callback_;
 
   // ServiceDirectory into which the CastRunner will publish itself.
   sys::OutgoingDirectory outgoing_directory_;
 
   std::unique_ptr<CastRunner> cast_runner_;
   fuchsia::sys::RunnerPtr cast_runner_ptr_;
-  base::TestComponentContextForProcess test_component_context_{
-      base::TestComponentContextForProcess::InitialState::kCloneAll};
+  fuchsia::sys::ComponentControllerPtr context_provider_controller_;
 };
 
 // A basic integration test ensuring a basic cast request launches the right
@@ -498,8 +431,28 @@
   app_config_manager_.AddApp(kTestAppId, app_url);
 
   CreateComponentContextAndStartComponent();
+  fuchsia::web::NavigationControllerPtr nav_controller;
+  cast_component_->frame()->GetNavigationController(
+      nav_controller.NewRequest());
 
-  CheckAppUrl(app_url);
+  // Ensure the NavigationState has the expected URL.
+  {
+    base::RunLoop run_loop;
+    cr_fuchsia::ResultReceiver<fuchsia::web::NavigationState> nav_entry(
+        run_loop.QuitClosure());
+    nav_controller->GetVisibleEntry(
+        cr_fuchsia::CallbackToFitFunction(nav_entry.GetReceiveCallback()));
+    run_loop.Run();
+    ASSERT_TRUE(nav_entry->has_url());
+    EXPECT_EQ(nav_entry->url(), app_url.spec());
+  }
+
+  EXPECT_FALSE(cast_runner_->is_headless());
+
+  // Verify that the component is torn down when |component_controller| is
+  // unbound.
+  component_controller_.Unbind();
+  WaitForComponentDestroyed();
 }
 
 // Verify that the Runner can continue to be used even after its Context has
@@ -509,46 +462,67 @@
   // Execute two iterations of launching the component and verifying that it
   // reaches the expected URL.
   for (int i = 0; i < 2; ++i) {
-    SCOPED_TRACE(testing::Message() << "Test iteration " << i);
-
     const GURL app_url = test_server_.GetURL(kBlankAppUrl);
     app_config_manager_.AddApp(kTestAppId, app_url);
 
     CreateComponentContextAndStartComponent();
 
-    CheckAppUrl(app_url);
+    fuchsia::web::NavigationControllerPtr nav_controller;
+    cast_component_->frame()->GetNavigationController(
+        nav_controller.NewRequest());
 
-    base::RunLoop kill_loop;
-    web_engine_controller_.events().OnTerminated =
-        [&kill_loop](int64_t return_code,
-                     fuchsia::sys::TerminationReason termination_reason) {
-          kill_loop.Quit();
-        };
-    web_engine_controller_->Kill();
+    base::RunLoop run_loop;
+    cr_fuchsia::ResultReceiver<fuchsia::web::NavigationState> nav_entry(
+        run_loop.QuitClosure());
+    nav_controller->GetVisibleEntry(
+        cr_fuchsia::CallbackToFitFunction(nav_entry.GetReceiveCallback()));
+    run_loop.Run();
 
+    ASSERT_TRUE(nav_entry->has_url());
+    EXPECT_EQ(nav_entry->url(), app_url.spec());
+
+    // Fake teardown of the Context, forcing the next StartComponent to create
+    // a new one.
+    cast_runner_->DisconnectContextForTest();
     WaitForComponentDestroyed();
-
-    // Wait for WebEngine to be terminated completely.
-    kill_loop.Run();
-
-    // Run the message loop to ensure the runner has a chance to handle context
-    // destruction.
-    base::RunLoop().RunUntilIdle();
-
-    // Start a new WebEngine instance for the next iteration.
-    if (i < 1)
-      StartAndPublishWebEngine();
   }
 }
 
 TEST_F(CastRunnerIntegrationTest, ApiBindings) {
-  app_config_manager_.AddApp(kTestAppId, test_server_.GetURL(kBlankAppUrl));
+  app_config_manager_.AddApp(kTestAppId, test_server_.GetURL(kEchoAppPath));
+
+  std::vector<chromium::cast::ApiBinding> binding_list;
+  chromium::cast::ApiBinding echo_binding;
+  echo_binding.set_before_load_script(cr_fuchsia::MemBufferFromString(
+      "window.echo = cast.__platform__.PortConnector.bind('echoService');",
+      "test"));
+  binding_list.emplace_back(std::move(echo_binding));
+  api_bindings_.set_bindings(std::move(binding_list));
 
   CreateComponentContextAndStartComponent();
 
-  // Verify that we can communicate with the binding added in
-  // CastRunnerIntegrationTest().
-  EXPECT_EQ(ExecuteJavaScript("1+2+\"\""), "3");
+  fuchsia::web::MessagePortPtr port =
+      api_bindings_.RunUntilMessagePortReceived("echoService").Bind();
+
+  fuchsia::web::WebMessage message;
+  message.set_data(cr_fuchsia::MemBufferFromString("ping", "ping-msg"));
+  port->PostMessage(std::move(message),
+                    [](fuchsia::web::MessagePort_PostMessage_Result result) {
+                      EXPECT_TRUE(result.is_response());
+                    });
+
+  base::RunLoop response_loop;
+  cr_fuchsia::ResultReceiver<fuchsia::web::WebMessage> response(
+      response_loop.QuitClosure());
+  port->ReceiveMessage(
+      cr_fuchsia::CallbackToFitFunction(response.GetReceiveCallback()));
+  response_loop.Run();
+
+  std::string response_string;
+  EXPECT_TRUE(
+      cr_fuchsia::StringFromMemBuffer(response->data(), &response_string));
+  EXPECT_EQ("ack ping", response_string);
+  EXPECT_TRUE(component_state_->api_bindings_has_clients());
 }
 
 TEST_F(CastRunnerIntegrationTest, IncorrectCastAppId) {
@@ -564,9 +538,12 @@
     EXPECT_EQ(status, ZX_ERR_PEER_CLOSED);
     run_loop.Quit();
   });
+  cr_fuchsia::ResultReceiver<WebComponent*> web_component(
+      run_loop.QuitClosure());
+  cast_runner_->SetWebComponentCreatedCallbackForTest(
+      AdaptCallbackForRepeating(web_component.GetReceiveCallback()));
   run_loop.Run();
-
-  EXPECT_FALSE(component_state_->api_bindings_has_clients());
+  EXPECT_FALSE(web_component.has_value());
 }
 
 TEST_F(CastRunnerIntegrationTest, UrlRequestRewriteRulesProvider) {
@@ -575,9 +552,20 @@
 
   CreateComponentContextAndStartComponent();
 
-  CheckAppUrl(echo_app_url);
+  // Bind a TestNavigationListener to the Frame.
+  cr_fuchsia::TestNavigationListener navigation_listener;
+  fidl::Binding<fuchsia::web::NavigationEventListener>
+      navigation_listener_binding(&navigation_listener);
+  cast_component_->frame()->SetNavigationEventListener(
+      navigation_listener_binding.NewBinding());
+  navigation_listener.RunUntilUrlEquals(echo_app_url);
 
-  EXPECT_EQ(ExecuteJavaScript("document.body.innerText"), "TestHeaderValue");
+  // Check the header was properly set.
+  base::Optional<base::Value> result = cr_fuchsia::ExecuteJavaScript(
+      cast_component_->frame(), "document.body.innerText");
+  ASSERT_TRUE(result);
+  ASSERT_TRUE(result->is_string());
+  EXPECT_EQ(result->GetString(), "Value");
 }
 
 TEST_F(CastRunnerIntegrationTest, ApplicationControllerBound) {
@@ -601,9 +589,25 @@
 
   CreateComponentContextAndStartComponent();
 
+  // Get the remote debugging port from the Context.
+  uint16_t remote_debugging_port = 0;
+  {
+    base::RunLoop run_loop;
+    cr_fuchsia::ResultReceiver<
+        fuchsia::web::Context_GetRemoteDebuggingPort_Result>
+        port_receiver(run_loop.QuitClosure());
+    cast_runner_->GetContext()->GetRemoteDebuggingPort(
+        cr_fuchsia::CallbackToFitFunction(port_receiver.GetReceiveCallback()));
+    run_loop.Run();
+
+    ASSERT_TRUE(port_receiver->is_response());
+    remote_debugging_port = port_receiver->response().port;
+    ASSERT_TRUE(remote_debugging_port != 0);
+  }
+
   // Connect to the debug service and ensure we get the proper response.
   base::Value devtools_list =
-      cr_fuchsia::GetDevToolsListFromPort(CastRunner::kRemoteDebuggingPort);
+      cr_fuchsia::GetDevToolsListFromPort(remote_debugging_port);
   ASSERT_TRUE(devtools_list.is_list());
   EXPECT_EQ(devtools_list.GetList().size(), 1u);
 
@@ -613,11 +617,23 @@
 }
 
 TEST_F(CastRunnerIntegrationTest, IsolatedContext) {
-  const GURL kContentDirectoryUrl("fuchsia-dir://testdata/empty.html");
+  const GURL kContentDirectoryUrl("fuchsia-dir://testdata/echo.html");
+
+  EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 0u);
 
   RegisterAppWithTestData(kContentDirectoryUrl);
+
   CreateComponentContextAndStartComponent();
-  CheckAppUrl(kContentDirectoryUrl);
+  EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 1u);
+
+  WaitUrlAndTitle(kContentDirectoryUrl, "echo");
+
+  // Verify that the component is torn down when |component_controller| is
+  // unbound.
+  component_controller_.Unbind();
+  WaitForComponentDestroyed();
+
+  EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 0u);
 }
 
 // Test the lack of CastAgent service does not cause a CastRunner crash.
@@ -639,6 +655,9 @@
   app_config_manager_.AddApp(kTestAppId, test_server_.GetURL(kEchoHeaderPath));
 
   CreateComponentContextAndStartComponent();
+  fuchsia::web::NavigationControllerPtr nav_controller;
+  cast_component_->frame()->GetNavigationController(
+      nav_controller.NewRequest());
 
   base::RunLoop run_loop;
   component_controller_.set_error_handler([&run_loop](zx_status_t error) {
@@ -665,7 +684,7 @@
 
   // Indicate that this app is to get bindings from a secondary agent.
   auto app_config = FakeApplicationConfigManager::CreateConfig(
-      kTestAppId, test_server_.GetURL(kBlankAppUrl));
+      kTestAppId, test_server_.GetURL(kEchoAppPath));
   app_config.set_agent_url(kDummyAgentUrl);
   app_config_manager_.AddAppConfig(std::move(app_config));
 
@@ -694,7 +713,6 @@
           }));
 
   StartCastComponent(component_url);
-  WaitComponentState();
 
   base::RunLoop().RunUntilIdle();
 
@@ -702,9 +720,6 @@
   EXPECT_FALSE(component_state_->api_bindings_has_clients());
   // Validate that the correct rewrite rules were requested.
   EXPECT_FALSE(component_state_->url_request_rules_provider_has_clients());
-
-  // Shutdown component before destroying dummy_agent_api_bindings.
-  ShutdownComponent();
 }
 
 // Test that when RewriteRules are not provided, a WebComponent is still
@@ -712,9 +727,10 @@
 // or RewriteRules.
 TEST_F(CastRunnerIntegrationTest, ApplicationConfigAgentUrlRewriteOptional) {
   TestApiBindings dummy_agent_api_bindings;
+
   // Indicate that this app is to get bindings from a secondary agent.
   auto app_config = FakeApplicationConfigManager::CreateConfig(
-      kTestAppId, test_server_.GetURL(kBlankAppUrl));
+      kTestAppId, test_server_.GetURL(kEchoAppPath));
   app_config.set_agent_url(kDummyAgentUrl);
   app_config_manager_.AddAppConfig(std::move(app_config));
 
@@ -743,7 +759,7 @@
           }));
 
   StartCastComponent(component_url);
-  WaitComponentState();
+  WaitComponentCreated();
 
   base::RunLoop().RunUntilIdle();
 
@@ -751,13 +767,10 @@
   EXPECT_FALSE(component_state_->api_bindings_has_clients());
   // Validate that the primary agent didn't provide its RewriteRules.
   EXPECT_FALSE(component_state_->url_request_rules_provider_has_clients());
-
-  // Shutdown component before destroying dummy_agent_api_bindings.
-  ShutdownComponent();
 }
 
-TEST_F(CastRunnerIntegrationTest, MicrophoneRedirect) {
-  GURL app_url = test_server_.GetURL("/microphone.html");
+TEST_F(CastRunnerIntegrationTest, MicRedirect) {
+  GURL app_url = test_server_.GetURL("/mic.html");
   auto app_config =
       FakeApplicationConfigManager::CreateConfig(kTestAppId, app_url);
 
@@ -766,57 +779,82 @@
   app_config.mutable_permissions()->push_back(std::move(mic_permission));
   app_config_manager_.AddAppConfig(std::move(app_config));
 
+  base::RunLoop run_loop;
+
+  init_component_state_callback_ = base::BindOnce(
+      [](base::OnceClosure quit_closure, FakeComponentState* component_state) {
+        component_state->outgoing_directory()->AddPublicService(
+            std::make_unique<vfs::Service>(
+                [quit_closure = std::move(quit_closure)](
+                    zx::channel channel,
+                    async_dispatcher_t* dispatcher) mutable {
+                  std::move(quit_closure).Run();
+                }),
+            fuchsia::media::Audio::Name_);
+      },
+      base::Passed(run_loop.QuitClosure()));
+
   CreateComponentContextAndStartComponent();
 
-  // Expect fuchsia.media.Audio connection to be redirected to the agent.
-  base::RunLoop run_loop;
-  component_state_->outgoing_directory()->AddPublicService(
-      std::make_unique<vfs::Service>(
-          [quit_closure = run_loop.QuitClosure()](
-              zx::channel channel, async_dispatcher_t* dispatcher) mutable {
-            std::move(quit_closure).Run();
-          }),
-      fuchsia::media::Audio::Name_);
-
-  ExecuteJavaScript("connectMicrophone();");
-
-  // Will quit once AudioCapturer is connected.
   run_loop.Run();
 }
 
 class HeadlessCastRunnerIntegrationTest : public CastRunnerIntegrationTest {
  public:
   HeadlessCastRunnerIntegrationTest()
-      : CastRunnerIntegrationTest(/*headless=*/true) {}
+      : CastRunnerIntegrationTest(fuchsia::web::ContextFeatureFlags::HEADLESS |
+                                  fuchsia::web::ContextFeatureFlags::NETWORK) {}
 };
 
 // A basic integration test ensuring a basic cast request launches the right
 // URL in the Chromium service.
 TEST_F(HeadlessCastRunnerIntegrationTest, Headless) {
+  ASSERT_TRUE(cast_runner_->is_headless());
+
   const char kAnimationPath[] = "/css_animation.html";
   const GURL animation_url = test_server_.GetURL(kAnimationPath);
   app_config_manager_.AddApp(kTestAppId, animation_url);
 
   CreateComponentContextAndStartComponent();
   auto tokens = scenic::ViewTokenPair::New();
+  cast_component_->CreateView(std::move(tokens.view_holder_token.value), {},
+                              {});
 
-  // Create a view.
-  auto view_provider =
-      component_services_client_->Connect<fuchsia::ui::app::ViewProvider>();
-  view_provider->CreateView(std::move(tokens.view_holder_token.value), {}, {});
+  WaitUrlAndTitle(animation_url, "animation finished");
 
-  api_bindings_.RunUntilMessagePortReceived("animation_finished");
+  // Verify that dropping the "view" EventPair is handled by the CastComponent.
+  {
+    base::RunLoop run_loop;
+    cast_component_->set_on_headless_disconnect_for_test(
+        run_loop.QuitClosure());
+    tokens.view_token.value.reset();
+    run_loop.Run();
+  }
 
-  // Verify that dropped "view" EventPair is handled properly.
-  tokens.view_token.value.reset();
-  api_bindings_.RunUntilMessagePortReceived("view_hidden");
+  component_controller_.Unbind();
+  base::RunLoop().RunUntilIdle();
 }
 
 // Isolated *and* headless? Doesn't sound like much fun!
 TEST_F(HeadlessCastRunnerIntegrationTest, IsolatedAndHeadless) {
-  const GURL kContentDirectoryUrl("fuchsia-dir://testdata/empty.html");
+  ASSERT_TRUE(cast_runner_->is_headless());
+
+  const GURL kContentDirectoryUrl("fuchsia-dir://testdata/echo.html");
+
+  EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 0u);
 
   RegisterAppWithTestData(kContentDirectoryUrl);
+
   CreateComponentContextAndStartComponent();
-  CheckAppUrl(kContentDirectoryUrl);
+  EXPECT_TRUE(cast_component_->runner()->is_headless());
+  EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 1u);
+
+  WaitUrlAndTitle(kContentDirectoryUrl, "echo");
+
+  // Verify that the component is torn down when |component_controller| is
+  // unbound.
+  component_controller_.Unbind();
+  WaitForComponentDestroyed();
+
+  EXPECT_EQ(cast_runner_->GetChildCastRunnerCountForTest(), 0u);
 }
diff --git a/fuchsia/runners/cast/main.cc b/fuchsia/runners/cast/main.cc
index 4e1e19a..a60f453 100644
--- a/fuchsia/runners/cast/main.cc
+++ b/fuchsia/runners/cast/main.cc
@@ -63,8 +63,8 @@
   create_context_params.set_user_agent_product("CrKey");
   create_context_params.set_user_agent_version("1.43");
 
-  create_context_params.set_remote_debugging_port(
-      CastRunner::kRemoteDebuggingPort);
+  const uint16_t kRemoteDebuggingPort = 9222;
+  create_context_params.set_remote_debugging_port(kRemoteDebuggingPort);
 
   // TODO(crbug.com/1023514): Remove this switch when it is no longer
   // necessary.
@@ -90,8 +90,8 @@
   WebContentRunner::GetContextParamsCallback get_context_params_callback =
       base::BindRepeating(&CreateMainContextParams);
 
-  CastRunner runner(std::move(get_context_params_callback), IsHeadless());
-  runner.PublishRunnerService(
+  CastRunner runner(
+      std::move(get_context_params_callback), IsHeadless(),
       base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get());
 
   base::fuchsia::ComponentContextForCurrentProcess()
diff --git a/fuchsia/runners/cast/test_api_bindings.cc b/fuchsia/runners/cast/test_api_bindings.cc
index 9a67165..ef99298 100644
--- a/fuchsia/runners/cast/test_api_bindings.cc
+++ b/fuchsia/runners/cast/test_api_bindings.cc
@@ -4,7 +4,6 @@
 
 #include "fuchsia/runners/cast/test_api_bindings.h"
 
-#include "base/fuchsia/fuchsia_logging.h"
 #include "base/run_loop.h"
 
 TestApiBindings::TestApiBindings() = default;
@@ -26,14 +25,7 @@
 }
 
 void TestApiBindings::GetAll(GetAllCallback callback) {
-  std::vector<chromium::cast::ApiBinding> bindings_clone;
-  for (auto& binding : bindings_) {
-    chromium::cast::ApiBinding binding_clone;
-    zx_status_t status = binding.Clone(&binding_clone);
-    ZX_CHECK(status == ZX_OK, status);
-    bindings_clone.push_back(std::move(binding_clone));
-  }
-  callback(std::move(bindings_clone));
+  callback(std::move(bindings_));
 }
 
 void TestApiBindings::Connect(
diff --git a/fuchsia/runners/cast/testdata/css_animation.html b/fuchsia/runners/cast/testdata/css_animation.html
index 53358fd..a24e50df 100644
--- a/fuchsia/runners/cast/testdata/css_animation.html
+++ b/fuchsia/runners/cast/testdata/css_animation.html
@@ -31,14 +31,14 @@
         isStarted = true;
       });
       animated.addEventListener('animationend', function() {
-        cast.__platform__.PortConnector.bind('animation_finished');
-
-        document.addEventListener("visibilitychange", ()=>{
-          if (document.hidden) {
-            cast.__platform__.PortConnector.bind('view_hidden');
-          }
-        }, false);
+        document.title = 'animation finished';
       });
+
+      // Indicates that no animation has run within a second of document load.
+      setTimeout(function() {
+        if (!isStarted)
+          document.title = 'animation never started';
+      }, 1000);
     </script>
   </body>
 </html>
diff --git a/fuchsia/runners/cast/testdata/empty.html b/fuchsia/runners/cast/testdata/empty.html
deleted file mode 100644
index 18ecdcb..0000000
--- a/fuchsia/runners/cast/testdata/empty.html
+++ /dev/null
@@ -1 +0,0 @@
-<html></html>
diff --git a/fuchsia/runners/cast/testdata/microphone.html b/fuchsia/runners/cast/testdata/mic.html
similarity index 81%
rename from fuchsia/runners/cast/testdata/microphone.html
rename to fuchsia/runners/cast/testdata/mic.html
index 0e142dc7..742b31b 100644
--- a/fuchsia/runners/cast/testdata/microphone.html
+++ b/fuchsia/runners/cast/testdata/mic.html
@@ -1,6 +1,4 @@
 <script>
-function connectMicrophone() {
     navigator.mediaDevices.getUserMedia({ audio: true, video: false })
         .then((stream) => { document.title = 'done'; });
-}
 </script>
\ No newline at end of file
diff --git a/fuchsia/runners/common/web_content_runner.cc b/fuchsia/runners/common/web_content_runner.cc
index b40597b..357ddc7 100644
--- a/fuchsia/runners/common/web_content_runner.cc
+++ b/fuchsia/runners/common/web_content_runner.cc
@@ -23,16 +23,17 @@
 #include "url/gurl.h"
 
 WebContentRunner::WebContentRunner(
-    GetContextParamsCallback get_context_params_callback)
-    : get_context_params_callback_(std::move(get_context_params_callback)) {}
-
-WebContentRunner::~WebContentRunner() = default;
-
-void WebContentRunner::PublishRunnerService(
-    sys::OutgoingDirectory* outgoing_directory) {
+    GetContextParamsCallback get_context_params_callback,
+    sys::OutgoingDirectory* outgoing_directory)
+    : get_context_params_callback_(std::move(get_context_params_callback)) {
   service_binding_.emplace(outgoing_directory, this);
 }
 
+WebContentRunner::WebContentRunner(fuchsia::web::ContextPtr context)
+    : context_(std::move(context)) {}
+
+WebContentRunner::~WebContentRunner() = default;
+
 fuchsia::web::ContextPtr WebContentRunner::CreateWebContext(
     fuchsia::web::CreateContextParams context_params) {
   fuchsia::web::ContextPtr web_context;
@@ -76,15 +77,34 @@
   RegisterComponent(std::move(component));
 }
 
+void WebContentRunner::SetWebComponentCreatedCallbackForTest(
+    base::RepeatingCallback<void(WebComponent*)> callback) {
+  DCHECK(components_.empty());
+  web_component_created_callback_for_test_ = std::move(callback);
+}
+
 void WebContentRunner::DestroyComponent(WebComponent* component) {
   components_.erase(components_.find(component));
 }
 
 void WebContentRunner::RegisterComponent(
     std::unique_ptr<WebComponent> component) {
+  if (web_component_created_callback_for_test_)
+    web_component_created_callback_for_test_.Run(component.get());
+
   components_.insert(std::move(component));
 }
 
+void WebContentRunner::SetContextProviderForTest(
+    fuchsia::web::ContextProviderPtr context_provider) {
+  DCHECK(context_provider);
+  context_provider_ = std::move(context_provider);
+}
+
+void WebContentRunner::DisconnectContextForTest() {
+  context_.Unbind();
+}
+
 fuchsia::web::ContextProvider* WebContentRunner::GetContextProvider() {
   if (!context_provider_) {
     context_provider_ = base::fuchsia::ComponentContextForCurrentProcess()
diff --git a/fuchsia/runners/common/web_content_runner.h b/fuchsia/runners/common/web_content_runner.h
index 623db0a..1d1d604 100644
--- a/fuchsia/runners/common/web_content_runner.h
+++ b/fuchsia/runners/common/web_content_runner.h
@@ -29,14 +29,18 @@
   // specified OutgoingDirectory.
   // |get_context_params_callback|: Returns parameters for the Runner's
   //     web.Context.
-  explicit WebContentRunner(
-      GetContextParamsCallback get_context_params_callback);
+  // |outgoing_directory|: The directory that the Runner's services will be
+  //     published to.
+  WebContentRunner(GetContextParamsCallback get_context_params_callback,
+                   sys::OutgoingDirectory* outgoing_directory);
+
+  // Creates a Runner which launches components using the specified |context|.
+  // The caller may publish the Runner, or call StartComponent() manually to
+  // create new components with it.
+  explicit WebContentRunner(fuchsia::web::ContextPtr context);
 
   ~WebContentRunner() override;
 
-  // Publishes the fuchsia.sys.Runner service to |outgoing_directory|.
-  void PublishRunnerService(sys::OutgoingDirectory* outgoing_directory);
-
   // TODO(crbug.com/1046615): Make this static when the injected ContextProvider
   // goes away.
   fuchsia::web::ContextPtr CreateWebContext(
@@ -55,9 +59,27 @@
                       fidl::InterfaceRequest<fuchsia::sys::ComponentController>
                           controller_request) override;
 
+  // Used by tests to asynchronously access the first WebComponent.
+  void SetWebComponentCreatedCallbackForTest(
+      base::RepeatingCallback<void(WebComponent*)> callback);
+
   // Registers a WebComponent, or specialization, with this Runner.
   void RegisterComponent(std::unique_ptr<WebComponent> component);
 
+  // Overrides the environment's the ContextProvider to use.
+  // TODO(crbug.com/1046615): Use test manifests for package specification.
+  void SetContextProviderForTest(
+      fuchsia::web::ContextProviderPtr context_provider);
+
+  // Disconnects the Context used by this Runner.
+  void DisconnectContextForTest();
+
+ protected:
+  base::RepeatingCallback<void(WebComponent*)>
+  web_component_created_callback_for_test() const {
+    return web_component_created_callback_for_test_;
+  }
+
  private:
   fuchsia::web::ContextProvider* GetContextProvider();
 
diff --git a/fuchsia/runners/web/main.cc b/fuchsia/runners/web/main.cc
index 3eaa55d..9ae6248 100644
--- a/fuchsia/runners/web/main.cc
+++ b/fuchsia/runners/web/main.cc
@@ -57,8 +57,8 @@
   WebContentRunner::GetContextParamsCallback get_context_params_callback =
       base::BindRepeating(&GetContextParams);
 
-  WebContentRunner runner(std::move(get_context_params_callback));
-  runner.PublishRunnerService(
+  WebContentRunner runner(
+      std::move(get_context_params_callback),
       base::fuchsia::ComponentContextForCurrentProcess()->outgoing().get());
 
   base::fuchsia::ComponentContextForCurrentProcess()
diff --git a/infra/config/buckets/ci.star b/infra/config/buckets/ci.star
index 0d007de..a8ae257 100644
--- a/infra/config/buckets/ci.star
+++ b/infra/config/buckets/ci.star
@@ -33,6 +33,25 @@
 )
 
 ci.console_view(
+    name = 'chromium.linux',
+    ordering = {
+        None: ['release', 'debug'],
+        'release': ci.ordering(short_names=['bld', 'tst', 'nsl', 'gcc']),
+        'cast': ci.ordering(short_names=['vid', 'aud']),
+    },
+)
+
+ci.console_view(
+    name = 'chromium.mac',
+    ordering = {
+        None: ['release'],
+        'release': ci.ordering(short_names=['bld']),
+        'debug': ci.ordering(short_names=['bld']),
+        'ios|default': ci.ordering(short_names=['dev', 'sim']),
+    },
+)
+
+ci.console_view(
     name = 'chromium.win',
     ordering = {
         None: ['release', 'debug'],
@@ -1626,13 +1645,22 @@
     name = 'GPU FYI XR Win x64 Builder',
 )
 
+
 ci.linux_builder(
     name = 'Cast Audio Linux',
+    console_view_entry = ci.console_view_entry(
+        category = 'cast',
+        short_name = 'aud',
+    ),
     ssd = True,
 )
 
 ci.linux_builder(
     name = 'Deterministic Fuchsia (dbg)',
+    console_view_entry = ci.console_view_entry(
+        category = 'fuchsia|x64',
+        short_name = 'det',
+    ),
     executable = 'recipe:swarming/deterministic_build',
     execution_timeout = 6 * time.hour,
     goma_jobs = None,
@@ -1640,12 +1668,20 @@
 
 ci.linux_builder(
     name = 'Deterministic Linux',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = 'det',
+    ),
     executable = 'recipe:swarming/deterministic_build',
     execution_timeout = 6 * time.hour,
 )
 
 ci.linux_builder(
     name = 'Deterministic Linux (dbg)',
+    console_view_entry = ci.console_view_entry(
+        category = 'debug|builder',
+        short_name = 'det',
+    ),
     cores = 32,
     executable = 'recipe:swarming/deterministic_build',
     execution_timeout = 6 * time.hour,
@@ -1657,24 +1693,44 @@
 
 ci.linux_builder(
     name = 'Linux Builder (dbg)(32)',
+    console_view_entry = ci.console_view_entry(
+        category = 'debug|builder',
+        short_name = '32',
+    ),
 )
 
 ci.linux_builder(
     name = 'Network Service Linux',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = 'nsl',
+    ),
 )
 
 ci.linux_builder(
     name = 'fuchsia-x64-dbg',
+    console_view_entry = ci.console_view_entry(
+        category = 'fuchsia|x64',
+        short_name = 'dbg',
+    ),
     notifies = ['cr-fuchsia'],
 )
 
 ci.linux_builder(
     name = 'linux-gcc-rel',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = 'gcc',
+    ),
     goma_backend = None,
 )
 
 ci.linux_builder(
     name = 'linux-trusty-rel',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = 'tru',
+    ),
     os = os.LINUX_TRUSTY,
 )
 
@@ -1689,11 +1745,19 @@
 
 ci.mac_ios_builder(
     name = 'ios-device',
+    console_view_entry = ci.console_view_entry(
+        category = 'ios|default',
+        short_name = 'dev',
+    ),
     executable = 'recipe:chromium',
 )
 
 ci.mac_ios_builder(
     name = 'ios-simulator-noncq',
+    console_view_entry = ci.console_view_entry(
+        category = 'ios|default',
+        short_name = 'non',
+    ),
 )
 
 
diff --git a/infra/config/consoles/chromium.linux.star b/infra/config/consoles/chromium.linux.star
deleted file mode 100644
index 3fb4bf1..0000000
--- a/infra/config/consoles/chromium.linux.star
+++ /dev/null
@@ -1,101 +0,0 @@
-luci.console_view(
-    name = 'chromium.linux',
-    header = '//consoles/chromium-header.textpb',
-    repo = 'https://chromium.googlesource.com/chromium/src',
-    entries = [
-        luci.console_view_entry(
-            builder = 'ci/Linux Builder',
-            category = 'release',
-            short_name = 'bld',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Linux Tests',
-            category = 'release',
-            short_name = 'tst',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Network Service Linux',
-            category = 'release',
-            short_name = 'nsl',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/linux-gcc-rel',
-            category = 'release',
-            short_name = 'gcc',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Deterministic Linux',
-            category = 'release',
-            short_name = 'det',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/linux-ozone-rel',
-            category = 'release',
-            short_name = 'ozo',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/linux-trusty-rel',
-            category = 'release',
-            short_name = 'tru',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Linux Builder (dbg)(32)',
-            category = 'debug|builder',
-            short_name = '32',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Linux Builder (dbg)',
-            category = 'debug|builder',
-            short_name = '64',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Deterministic Linux (dbg)',
-            category = 'debug|builder',
-            short_name = 'det',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Linux Tests (dbg)(1)',
-            category = 'debug|tester',
-            short_name = '64',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Cast Linux',
-            category = 'cast',
-            short_name = 'vid',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Cast Audio Linux',
-            category = 'cast',
-            short_name = 'aud',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Fuchsia ARM64',
-            category = 'fuchsia|a64',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/fuchsia-arm64-cast',
-            category = 'fuchsia|cast',
-            short_name = 'a64',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/fuchsia-x64-cast',
-            category = 'fuchsia|cast',
-            short_name = 'x64',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/fuchsia-x64-dbg',
-            category = 'fuchsia|x64',
-            short_name = 'dbg',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Deterministic Fuchsia (dbg)',
-            category = 'fuchsia|x64',
-            short_name = 'det',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Fuchsia x64',
-            category = 'fuchsia|x64',
-            short_name = 'rel',
-        ),
-    ],
-)
diff --git a/infra/config/consoles/chromium.mac.star b/infra/config/consoles/chromium.mac.star
deleted file mode 100644
index fd87727f..0000000
--- a/infra/config/consoles/chromium.mac.star
+++ /dev/null
@@ -1,72 +0,0 @@
-luci.console_view(
-    name = 'chromium.mac',
-    header = '//consoles/chromium-header.textpb',
-    repo = 'https://chromium.googlesource.com/chromium/src',
-    entries = [
-        luci.console_view_entry(
-            builder = 'ci/Mac Builder',
-            category = 'release',
-            short_name = 'bld',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Mac10.10 Tests',
-            category = 'release',
-            short_name = '10',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Mac10.11 Tests',
-            category = 'release',
-            short_name = '11',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Mac10.12 Tests',
-            category = 'release',
-            short_name = '12',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Mac10.13 Tests',
-            category = 'release',
-            short_name = '13',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Mac10.14 Tests',
-            category = 'release',
-            short_name = '14',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/WebKit Mac10.13 (retina)',
-            category = 'release',
-            short_name = 'ret',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Mac Builder (dbg)',
-            category = 'debug',
-            short_name = 'bld',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/Mac10.13 Tests (dbg)',
-            category = 'debug',
-            short_name = '13',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/ios-device',
-            category = 'ios|default',
-            short_name = 'dev',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/ios-simulator',
-            category = 'ios|default',
-            short_name = 'sim',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/ios-simulator-full-configs',
-            category = 'ios|default',
-            short_name = 'ful',
-        ),
-        luci.console_view_entry(
-            builder = 'ci/ios-simulator-noncq',
-            category = 'ios|default',
-            short_name = 'non',
-        ),
-    ],
-)
diff --git a/infra/config/main.star b/infra/config/main.star
index 8480c3dc..6e10b2a 100755
--- a/infra/config/main.star
+++ b/infra/config/main.star
@@ -116,8 +116,6 @@
 exec('//consoles/chromium.goma.migration.star')
 exec('//consoles/chromium.gpu.star')
 exec('//consoles/chromium.gpu.fyi.star')
-exec('//consoles/chromium.linux.star')
-exec('//consoles/chromium.mac.star')
 exec('//consoles/chromium.memory.star')
 exec('//consoles/chromium.swangle.star')
 exec('//consoles/chromium.webrtc.star')
diff --git a/infra/config/versioned/trunk/buckets/ci.star b/infra/config/versioned/trunk/buckets/ci.star
index 29b72f9..92696186 100644
--- a/infra/config/versioned/trunk/buckets/ci.star
+++ b/infra/config/versioned/trunk/buckets/ci.star
@@ -323,50 +323,89 @@
 
 ci.linux_builder(
     name = 'Cast Linux',
+    console_view_entry = ci.console_view_entry(
+        category = 'cast',
+        short_name = 'vid',
+    ),
     goma_jobs = goma.jobs.J50,
 )
 
 ci.linux_builder(
     name = 'Fuchsia ARM64',
+    console_view_entry = ci.console_view_entry(
+        category = 'fuchsia|a64',
+    ),
     notifies = ['cr-fuchsia'],
 )
 
 ci.linux_builder(
     name = 'Fuchsia x64',
+    console_view_entry = ci.console_view_entry(
+        category = 'fuchsia|x64',
+        short_name = 'rel',
+    ),
     notifies = ['cr-fuchsia'],
 )
 
 ci.linux_builder(
     name = 'Linux Builder',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = 'bld',
+    ),
 )
 
 ci.linux_builder(
     name = 'Linux Builder (dbg)',
+    console_view_entry = ci.console_view_entry(
+        category = 'debug|builder',
+        short_name = '64',
+    ),
 )
 
 ci.linux_builder(
     name = 'Linux Tests',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = 'tst',
+    ),
     goma_backend = None,
     triggered_by = [builder_name('Linux Builder')],
 )
 
 ci.linux_builder(
     name = 'Linux Tests (dbg)(1)',
+    console_view_entry = ci.console_view_entry(
+        category = 'debug|tester',
+        short_name = '64',
+    ),
     triggered_by = [builder_name('Linux Builder (dbg)')],
 )
 
 ci.linux_builder(
     name = 'fuchsia-arm64-cast',
+    console_view_entry = ci.console_view_entry(
+        category = 'fuchsia|cast',
+        short_name = 'a64',
+    ),
     notifies = ['cr-fuchsia'],
 )
 
 ci.linux_builder(
     name = 'fuchsia-x64-cast',
+    console_view_entry = ci.console_view_entry(
+        category = 'fuchsia|cast',
+        short_name = 'x64',
+    ),
     notifies = ['cr-fuchsia'],
 )
 
 ci.linux_builder(
     name = 'linux-ozone-rel',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = 'ozo',
+    ),
 )
 
 ci.linux_builder(
@@ -387,52 +426,88 @@
 
 ci.mac_builder(
     name = 'Mac Builder',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = 'bld',
+    ),
     os = os.MAC_10_14,
 )
 
 ci.mac_builder(
     name = 'Mac Builder (dbg)',
+    console_view_entry = ci.console_view_entry(
+        category = 'debug',
+        short_name = 'bld',
+    ),
     os = os.MAC_ANY,
 )
 
 # The build runs on 10.13, but triggers tests on 10.10 bots.
 ci.mac_builder(
     name = 'Mac10.10 Tests',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = '10',
+    ),
     triggered_by = [builder_name('Mac Builder')],
 )
 
 # The build runs on 10.13, but triggers tests on 10.11 bots.
 ci.mac_builder(
     name = 'Mac10.11 Tests',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = '11',
+    ),
     triggered_by = [builder_name('Mac Builder')],
 )
 
 ci.mac_builder(
     name = 'Mac10.12 Tests',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = '12',
+    ),
     os = os.MAC_10_12,
     triggered_by = [builder_name('Mac Builder')],
 )
 
 ci.mac_builder(
     name = 'Mac10.13 Tests',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = '13',
+    ),
     os = os.MAC_10_13,
     triggered_by = [builder_name('Mac Builder')],
 )
 
 ci.mac_builder(
     name = 'Mac10.14 Tests',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = '14',
+    ),
     os = os.MAC_10_14,
     triggered_by = [builder_name('Mac Builder')],
 )
 
 ci.mac_builder(
     name = 'Mac10.13 Tests (dbg)',
+    console_view_entry = ci.console_view_entry(
+        category = 'debug',
+        short_name = '13',
+    ),
     os = os.MAC_ANY,
     triggered_by = [builder_name('Mac Builder (dbg)')],
 )
 
 ci.mac_builder(
     name = 'WebKit Mac10.13 (retina)',
+    console_view_entry = ci.console_view_entry(
+        category = 'release',
+        short_name = 'ret',
+    ),
     os = os.MAC_10_13,
     triggered_by = [builder_name('Mac Builder')],
 )
@@ -440,6 +515,10 @@
 
 ci.mac_ios_builder(
     name = 'ios-simulator',
+    console_view_entry = ci.console_view_entry(
+        category = 'ios|default',
+        short_name = 'sim',
+    ),
     executable = 'recipe:chromium',
     properties = {
         'xcode_build_version': '11c29',
@@ -448,6 +527,10 @@
 
 ci.mac_ios_builder(
     name = 'ios-simulator-full-configs',
+    console_view_entry = ci.console_view_entry(
+        category = 'ios|default',
+        short_name = 'ful',
+    ),
     executable = 'recipe:chromium',
 )
 
diff --git a/ios/chrome/app/strings/resources/ios_strings_bn.xtb b/ios/chrome/app/strings/resources/ios_strings_bn.xtb
index 015d8b0..495a42a 100644
--- a/ios/chrome/app/strings/resources/ios_strings_bn.xtb
+++ b/ios/chrome/app/strings/resources/ios_strings_bn.xtb
@@ -168,6 +168,7 @@
 <translation id="3112556859945124369">চিহ্নিত করুন…</translation>
 <translation id="3153862085237805241">কার্ড সেভ করুন</translation>
 <translation id="3157684681743766797">সবগুলি চিহ্নিত করুন…</translation>
+<translation id="3161291298470460782">এর ফলে আপনি অ্যাকাউন্ট থেকে সাইন-আউট হয়ে যাবেন, সিঙ্ক করার সুবিধা বন্ধ হয়ে যাবে এবং এই ডিভাইস থেকে Chrome-এর সমস্ত ডেটা মুছে যাবে। আপনি যেসব ডেটা সিঙ্ক করেছেন, সেগুলি আপনার Google অ্যাকাউন্টেই থেকে যাবে।</translation>
 <translation id="3175081911749765310">ওয়েব পরিষেবা</translation>
 <translation id="3178650076442119961">আজ ব্যবহার করা হয়েছে</translation>
 <translation id="3207960819495026254">বুকমার্ক করা হয়েছে</translation>
@@ -200,6 +201,7 @@
 <translation id="3494788280727468875">ব্রাউজ করা ডেটা সাফ করার বিষয়টি নিশ্চিত করুন</translation>
 <translation id="35083190962747987">${url} খুলুন</translation>
 <translation id="3519193562722059437">ওয়েব ব্রাউজ করার জন্য একটি ট্যাব খুলুন।</translation>
+<translation id="3523473570015918798">সাইন-আউট করে নিলে, আপনার সেভ করা বুকমার্ক, সার্চ করার ইতিহাস, পাসওয়ার্ড ও Chrome-এর অন্যান্য ডেটা আপনার Google অ্যাকাউন্টে আর সিঙ্ক করা যাবে না।</translation>
 <translation id="3527085408025491307">ফোল্ডার</translation>
 <translation id="3529024052484145543">সুরক্ষিত নয়</translation>
 <translation id="3533202363250687977">সব ছদ্মবেশী ট্যাব বন্ধ করুন</translation>
@@ -333,6 +335,7 @@
 <translation id="54401264925851789">পৃষ্ঠা নিরাপত্তা তথ্য</translation>
 <translation id="5443952882982198570">ক্রেডিট কার্ড</translation>
 <translation id="5457907402803865181">পাসওয়ার্ড সিঙ্কে সমস্যা হচ্ছে।</translation>
+<translation id="5508435575041083207">সাইন-আউট করুন এবং এই ডিভাইসে থাকা ডেটা মুছে ফেলুন</translation>
 <translation id="5525269841082836315">পাসফ্রেজ তৈরি করুন</translation>
 <translation id="5548760955356983418">Handoff এই ডিভাইসে একটি ওয়েবসাইট ব্রাউজ করা শুরু করতে দেয় এবং পরে সহজেই আপনার Mac-এ অবিরত করতে দেয়৷ সাম্প্রতিক খোলা ওয়েবসাইটটি আপনার Mac-এ ডক-এ প্রদর্শিত হবে৷
 
@@ -507,6 +510,9 @@
 <translation id="766891008101699113">ব্যক্তিগতভাবে ওয়েব ব্রাউজ করতে, একটি নতুন ট্যাব যোগ করুন।</translation>
 <translation id="7671141431838911305">ইনস্টল করুন</translation>
 <translation id="7765158879357617694">সরান</translation>
+<translation id="7771470029643830783">সাইন-আউট করে নিলে, আপনার সেভ করা বুকমার্ক, সার্চ করার ইতিহাস, পাসওয়ার্ড ও Chrome-এর অন্যান্য ডেটা আপনার Google অ্যাকাউন্টে আর সিঙ্ক করা যাবে না।
+
+যেহেতু <ph name="HOSTED_DOMAIN" /> আপনার অ্যাকাউন্ট ম্যানেজ করে, তাই সাইন-আউট করে নিলেই, Chrome-এ থাকা আপনার সমস্ত ডেটা এই ডিভাইস থেকে মুছে যাবে। আপনি যেসব ডেটা সিঙ্ক করেছেন, সেগুলি আপনার Google অ্যাকাউন্টেই থেকে যাবে।</translation>
 <translation id="7772032839648071052">পাসফ্রেজ নিশ্চিত করুন</translation>
 <translation id="7781011649027948662">পৃষ্ঠাটি অনুবাদ করতে চান?</translation>
 <translation id="7781829728241885113">গতকাল</translation>
@@ -556,6 +562,7 @@
 <translation id="8490978609246021741">পরিবর্তনগুলি সেভ করুন</translation>
 <translation id="8503813439785031346">ইউজারনেম</translation>
 <translation id="850600235656508448">ছদ্মবেশী ট্যাবে খুলুন</translation>
+<translation id="8510057420705599706">এর ফলে আপনি অ্যাকাউন্ট থেকে সাইন-আউট হয়ে যাবেন এবং সিঙ্ক করার সুবিধা বন্ধ হয়ে যাবে, কিন্তু আপনার সেভ করা বুকমার্ক, সার্চ করার ইতিহাস, পাসওয়ার্ড ও Chrome-এর অন্যান্য ডেটা এই ডিভাইসেই রয়ে যাবে।</translation>
 <translation id="8517375800490286174">ওপেন সোর্স লাইসেন্স</translation>
 <translation id="8524799873541103884"><ph name="NUMBER_OF_OPEN_TABS" />টির মধ্যে <ph name="FIRST_VISIBLE_TAB" /> থেকে <ph name="LAST_VISIBLE_TAB" /> পর্যন্ত <ph name="INCOGNITO" /> ট্যাব</translation>
 <translation id="8529767659511976195">নতুন</translation>
@@ -598,6 +605,7 @@
 <translation id="9094033019050270033">পাসওয়ার্ড আপডেট করুন</translation>
 <translation id="9100610230175265781">পাসফ্রেজের প্রয়োজন</translation>
 <translation id="9148126808321036104">আবার সাইন-ইন করুন</translation>
+<translation id="9152539721251340337">একটি QR কোড তৈরি করুন</translation>
 <translation id="9157836665414082580">ডায়ালগ রুদ্ধ করুন</translation>
 <translation id="9188680907066685419">ম্যানেজ করা অ্যাকাউন্ট থেকে সাইন-আউট করুন</translation>
 <translation id="9203116392574189331">Handoff</translation>
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn
index adf96cc..43ea65f 100644
--- a/ios/chrome/browser/BUILD.gn
+++ b/ios/chrome/browser/BUILD.gn
@@ -105,7 +105,6 @@
     "//ios/chrome/browser/sync/glue",
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
-    "//ios/chrome/browser/ui/dialogs:feature_flags",
     "//ios/chrome/browser/ui/fullscreen:feature_flags",
     "//ios/chrome/browser/ui/omnibox",
     "//ios/chrome/browser/ui/toolbar/public:feature_flags",
diff --git a/ios/chrome/browser/app_launcher/BUILD.gn b/ios/chrome/browser/app_launcher/BUILD.gn
index 5cd4023..32b65406 100644
--- a/ios/chrome/browser/app_launcher/BUILD.gn
+++ b/ios/chrome/browser/app_launcher/BUILD.gn
@@ -9,9 +9,13 @@
   sources = [
     "app_launcher_abuse_detector.h",
     "app_launcher_abuse_detector.mm",
+    "app_launcher_browser_agent.h",
+    "app_launcher_browser_agent.mm",
     "app_launcher_tab_helper.h",
     "app_launcher_tab_helper.mm",
     "app_launcher_tab_helper_delegate.h",
+    "app_launcher_util.h",
+    "app_launcher_util.mm",
     "app_launching_state.h",
     "app_launching_state.mm",
   ]
@@ -20,38 +24,61 @@
     "//components/reading_list/core:core",
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
+    "//ios/chrome/browser/main:public",
     "//ios/chrome/browser/overlays",
     "//ios/chrome/browser/overlays/public/web_content_area",
     "//ios/chrome/browser/reading_list",
     "//ios/chrome/browser/u2f",
-    "//ios/chrome/browser/ui/dialogs:feature_flags",
+    "//ios/chrome/browser/web_state_list",
+    "//ios/public/provider/chrome/browser",
+    "//ios/public/provider/chrome/browser/mailto",
     "//ios/web/common",
     "//ios/web/public",
     "//url",
   ]
 }
 
+source_set("test_support") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  testonly = true
+  sources = [
+    "fake_app_launcher_abuse_detector.h",
+    "fake_app_launcher_abuse_detector.mm",
+  ]
+  deps = [
+    ":app_launcher",
+    "//base",
+  ]
+}
+
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
     "app_launcher_abuse_detector_unittest.mm",
+    "app_launcher_browser_agent_unittest.mm",
     "app_launcher_tab_helper_unittest.mm",
     "app_launching_state_unittest.mm",
   ]
   deps = [
     ":app_launcher",
+    ":test_support",
     "//base",
     "//base/test:test_support",
     "//components/reading_list/core:core",
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state:test_support",
+    "//ios/chrome/browser/main:test_support",
+    "//ios/chrome/browser/overlays",
+    "//ios/chrome/browser/overlays/public/web_content_area",
     "//ios/chrome/browser/reading_list",
     "//ios/chrome/browser/u2f",
     "//ios/chrome/browser/web:tab_id_tab_helper",
     "//ios/chrome/browser/web:web_internal",
+    "//ios/chrome/browser/web_state_list",
     "//ios/web/public/test/fakes",
     "//testing/gtest",
+    "//third_party/ocmock",
     "//url",
   ]
 }
diff --git a/ios/chrome/browser/app_launcher/app_launcher_browser_agent.h b/ios/chrome/browser/app_launcher/app_launcher_browser_agent.h
new file mode 100644
index 0000000..2d5fc4c
--- /dev/null
+++ b/ios/chrome/browser/app_launcher/app_launcher_browser_agent.h
@@ -0,0 +1,107 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_APP_LAUNCHER_APP_LAUNCHER_BROWSER_AGENT_H_
+#define IOS_CHROME_BROWSER_APP_LAUNCHER_APP_LAUNCHER_BROWSER_AGENT_H_
+
+#include "base/scoped_observer.h"
+#import "ios/chrome/browser/app_launcher/app_launcher_tab_helper_delegate.h"
+#import "ios/chrome/browser/main/browser_observer.h"
+#import "ios/chrome/browser/main/browser_user_data.h"
+#import "ios/chrome/browser/web_state_list/web_state_list_observer.h"
+
+class OverlayRequestQueue;
+
+// A browser agent that manages opening external apps for navigations that occur
+// within one of the Browser's WebStates.
+class AppLauncherBrowserAgent
+    : public BrowserUserData<AppLauncherBrowserAgent> {
+ public:
+  ~AppLauncherBrowserAgent() override;
+
+ private:
+  explicit AppLauncherBrowserAgent(Browser* browser);
+  friend class BrowserUserData<AppLauncherBrowserAgent>;
+
+  // Helper object that handles delegated AppLauncherTabHelper functionality.
+  class TabHelperDelegate : public AppLauncherTabHelperDelegate {
+   public:
+    explicit TabHelperDelegate(WebStateList* web_state_list);
+    ~TabHelperDelegate() override;
+
+   private:
+    // AppLauncherTabHelperDelegate:
+    void LaunchAppForTabHelper(AppLauncherTabHelper* tab_helper,
+                               const GURL& url,
+                               bool link_transition) override;
+    void ShowRepeatedAppLaunchAlert(
+        AppLauncherTabHelper* tab_helper,
+        base::OnceCallback<void(bool)> completion) override;
+
+    // Returns the OverlayRequestQueue to use for app launch dialogs from
+    // |web_state|.  Returns the queue for |web_state|'s opener if |web_state|
+    // is expected to be closed before the app launcher dialog can be shown.
+    OverlayRequestQueue* GetQueueForAppLaunchDialog(web::WebState* web_state);
+
+    // The Browser's WebStateList.  Used to fetch the appropriate request queue
+    // for app launcher dialogs.
+    WebStateList* web_state_list_ = nullptr;
+  };
+
+  // Helper object that sets up the delegates for all AppLauncherTabHelpers in
+  // the Browser's WebStateList.
+  class TabHelperDelegateInstaller : public WebStateListObserver {
+   public:
+    TabHelperDelegateInstaller(AppLauncherTabHelperDelegate* delegate,
+                               WebStateList* web_state_list);
+    ~TabHelperDelegateInstaller() override;
+
+   private:
+    // WebStateListObserver:
+    void WebStateInsertedAt(WebStateList* web_state_list,
+                            web::WebState* web_state,
+                            int index,
+                            bool activating) override;
+    void WebStateReplacedAt(WebStateList* web_state_list,
+                            web::WebState* old_web_state,
+                            web::WebState* new_web_state,
+                            int index) override;
+    void WillDetachWebStateAt(WebStateList* web_state_list,
+                              web::WebState* web_state,
+                              int index) override;
+
+    // The delegate that is installed for each WebState in the WebStateList.
+    AppLauncherTabHelperDelegate* delegate_ = nullptr;
+  };
+
+  // Helper object that unhooks the delegate installer when the Browser is
+  // destroyed.
+  class BrowserShutdownHelper : public BrowserObserver {
+   public:
+    BrowserShutdownHelper(Browser* browser,
+                          WebStateListObserver* web_state_list_observer);
+    ~BrowserShutdownHelper() override;
+
+   private:
+    // BrowserObserver:
+    void BrowserDestroyed(Browser* browser) override;
+
+    // The WebStateListObserver to detach upon destruction.
+    WebStateListObserver* web_state_list_observer_ = nullptr;
+    // Scoped observer for the Browser.
+    ScopedObserver<Browser, BrowserObserver> scoped_observer_{this};
+  };
+
+  // Handler for app launches in the Browser.
+  TabHelperDelegate tab_helper_delegate_;
+  // Installer for tab helper delegates.
+  TabHelperDelegateInstaller tab_helper_delegate_installer_;
+  // Helper object for cleaning up the BrowserAgent when the Browser is
+  // destroyed.
+  BrowserShutdownHelper shutdown_helper_;
+  // BrowserUserData key.
+  BROWSER_USER_DATA_KEY_DECL();
+};
+
+#endif  // IOS_CHROME_BROWSER_APP_LAUNCHER_APP_LAUNCHER_BROWSER_AGENT_H_
diff --git a/ios/chrome/browser/app_launcher/app_launcher_browser_agent.mm b/ios/chrome/browser/app_launcher/app_launcher_browser_agent.mm
new file mode 100644
index 0000000..65b9066
--- /dev/null
+++ b/ios/chrome/browser/app_launcher/app_launcher_browser_agent.mm
@@ -0,0 +1,230 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/app_launcher/app_launcher_browser_agent.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#import "ios/chrome/browser/app_launcher/app_launcher_tab_helper.h"
+#import "ios/chrome/browser/app_launcher/app_launcher_util.h"
+#import "ios/chrome/browser/main/browser.h"
+#include "ios/chrome/browser/overlays/public/overlay_callback_manager.h"
+#import "ios/chrome/browser/overlays/public/overlay_request.h"
+#import "ios/chrome/browser/overlays/public/overlay_request_queue.h"
+#import "ios/chrome/browser/overlays/public/overlay_response.h"
+#import "ios/chrome/browser/overlays/public/web_content_area/app_launcher_alert_overlay.h"
+#import "ios/chrome/browser/web_state_list/web_state_list.h"
+#import "ios/chrome/browser/web_state_list/web_state_opener.h"
+#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
+#include "ios/public/provider/chrome/browser/mailto/mailto_handler_provider.h"
+#import "ios/web/public/navigation/navigation_manager.h"
+#import "ios/web/public/web_state.h"
+#import "net/base/mac/url_conversions.h"
+#include "url/gurl.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+BROWSER_USER_DATA_KEY_IMPL(AppLauncherBrowserAgent)
+
+namespace {
+// Records histogram metric on the user's response when prompted to open another
+// application. |user_accepted| should be YES if the user accepted the prompt to
+// launch another application. This call is extracted to a separate function to
+// reduce macro code expansion.
+void RecordUserAcceptedAppLaunchMetric(BOOL user_accepted) {
+  UMA_HISTOGRAM_BOOLEAN("Tab.ExternalApplicationOpened", user_accepted);
+}
+
+// Callback for the app launcher alert overlay.
+void AppLauncherOverlayCallback(base::OnceCallback<void(bool)> completion,
+                                bool repeated_request,
+                                OverlayResponse* response) {
+  // Extract the user decision from |response|.
+  bool user_accepted = false;
+  if (response) {
+    AppLauncherAlertOverlayResponseInfo* info =
+        response->GetInfo<AppLauncherAlertOverlayResponseInfo>();
+    user_accepted = info && info->allow_navigation();
+  }
+
+  // Record the UMA for repeated requests.
+  if (repeated_request)
+    RecordUserAcceptedAppLaunchMetric(user_accepted);
+
+  // Execute the completion with the response.
+  DCHECK(!completion.is_null());
+  std::move(completion).Run(user_accepted);
+}
+
+// Launches the app for |url| if |user_accepted| is true.
+void LaunchExternalApp(const GURL url, bool user_accepted = true) {
+  if (!user_accepted)
+    return;
+  [[UIApplication sharedApplication] openURL:net::NSURLWithGURL(url)
+                                     options:@{}
+                           completionHandler:nil];
+}
+}  // namespace
+
+#pragma mark - AppLauncherBrowserAgent
+
+AppLauncherBrowserAgent::AppLauncherBrowserAgent(Browser* browser)
+    : tab_helper_delegate_(browser->GetWebStateList()),
+      tab_helper_delegate_installer_(&tab_helper_delegate_,
+                                     browser->GetWebStateList()),
+      shutdown_helper_(browser, &tab_helper_delegate_installer_) {}
+
+AppLauncherBrowserAgent::~AppLauncherBrowserAgent() = default;
+
+#pragma mark - AppLauncherBrowserAgent::TabHelperDelegate
+
+AppLauncherBrowserAgent::TabHelperDelegate::TabHelperDelegate(
+    WebStateList* web_state_list)
+    : web_state_list_(web_state_list) {
+  DCHECK(web_state_list_);
+}
+
+AppLauncherBrowserAgent::TabHelperDelegate::~TabHelperDelegate() = default;
+
+#pragma mark AppLauncherTabHelperDelegate
+
+void AppLauncherBrowserAgent::TabHelperDelegate::LaunchAppForTabHelper(
+    AppLauncherTabHelper* tab_helper,
+    const GURL& url,
+    bool link_transition) {
+  // Don't open application if chrome is not active.
+  if ([[UIApplication sharedApplication] applicationState] !=
+      UIApplicationStateActive) {
+    return;
+  }
+
+  // Uses a Mailto Handler to open the appropriate app.
+  if (url.SchemeIs(url::kMailToScheme)) {
+    MailtoHandlerProvider* provider =
+        ios::GetChromeBrowserProvider()->GetMailtoHandlerProvider();
+    provider->HandleMailtoURL(net::NSURLWithGURL(url));
+    return;
+  }
+
+  // Show the a dialog for app store launches and external URL navigations that
+  // did not originate from a link tap.
+  bool show_dialog = UrlHasAppStoreScheme(url) || !link_transition;
+  if (show_dialog) {
+    std::unique_ptr<OverlayRequest> request =
+        OverlayRequest::CreateWithConfig<AppLauncherAlertOverlayRequestConfig>(
+            /*is_repeated_request=*/false);
+    request->GetCallbackManager()->AddCompletionCallback(base::BindOnce(
+        &AppLauncherOverlayCallback, base::BindOnce(&LaunchExternalApp, url),
+        /*repeated_request=*/false));
+    GetQueueForAppLaunchDialog(tab_helper->web_state())
+        ->AddRequest(std::move(request));
+  } else {
+    LaunchExternalApp(url);
+  }
+}
+
+void AppLauncherBrowserAgent::TabHelperDelegate::ShowRepeatedAppLaunchAlert(
+    AppLauncherTabHelper* tab_helper,
+    base::OnceCallback<void(bool)> completion) {
+  std::unique_ptr<OverlayRequest> request =
+      OverlayRequest::CreateWithConfig<AppLauncherAlertOverlayRequestConfig>(
+          /*is_repeated_request=*/true);
+  request->GetCallbackManager()->AddCompletionCallback(
+      base::BindOnce(&AppLauncherOverlayCallback, std::move(completion),
+                     /*is_repeated_request=*/true));
+  GetQueueForAppLaunchDialog(tab_helper->web_state())
+      ->AddRequest(std::move(request));
+}
+
+#pragma mark Private
+
+OverlayRequestQueue*
+AppLauncherBrowserAgent::TabHelperDelegate::GetQueueForAppLaunchDialog(
+    web::WebState* web_state) {
+  web::WebState* queue_web_state = web_state;
+  // If an app launch navigation is occurring in a new tab, the tab will be
+  // closed immediately after the navigation fails, cancelling the app launcher
+  // dialog before it gets a chance to be shown.  When this occurs, use the
+  // OverlayRequestQueue for the tab's opener instead.
+  if (!web_state->GetNavigationManager()->GetItemCount() &&
+      web_state->HasOpener()) {
+    int index = web_state_list_->GetIndexOfWebState(web_state);
+    queue_web_state =
+        web_state_list_->GetOpenerOfWebStateAt(index).opener ?: queue_web_state;
+  }
+  return OverlayRequestQueue::FromWebState(queue_web_state,
+                                           OverlayModality::kWebContentArea);
+}
+
+#pragma mark - AppLauncherBrowserAgent::TabHelperDelegateInstaller
+
+AppLauncherBrowserAgent::TabHelperDelegateInstaller::TabHelperDelegateInstaller(
+    AppLauncherTabHelperDelegate* delegate,
+    WebStateList* web_state_list)
+    : delegate_(delegate) {
+  DCHECK(delegate_);
+  DCHECK(web_state_list);
+  for (int i = 0; i < web_state_list->count(); ++i) {
+    AppLauncherTabHelper::FromWebState(web_state_list->GetWebStateAt(i))
+        ->SetDelegate(delegate_);
+  }
+}
+
+AppLauncherBrowserAgent::TabHelperDelegateInstaller::
+    ~TabHelperDelegateInstaller() = default;
+
+#pragma mark WebStateListObserver
+
+void AppLauncherBrowserAgent::TabHelperDelegateInstaller::WebStateInsertedAt(
+    WebStateList* web_state_list,
+    web::WebState* web_state,
+    int index,
+    bool activating) {
+  AppLauncherTabHelper::FromWebState(web_state)->SetDelegate(delegate_);
+}
+
+void AppLauncherBrowserAgent::TabHelperDelegateInstaller::WebStateReplacedAt(
+    WebStateList* web_state_list,
+    web::WebState* old_web_state,
+    web::WebState* new_web_state,
+    int index) {
+  AppLauncherTabHelper::FromWebState(old_web_state)->SetDelegate(nullptr);
+  AppLauncherTabHelper::FromWebState(new_web_state)->SetDelegate(delegate_);
+}
+
+void AppLauncherBrowserAgent::TabHelperDelegateInstaller::WillDetachWebStateAt(
+    WebStateList* web_state_list,
+    web::WebState* web_state,
+    int index) {
+  AppLauncherTabHelper::FromWebState(web_state)->SetDelegate(nullptr);
+}
+
+#pragma mark - AppLauncherBrowserAgent::BrowserShutdownHelper
+
+AppLauncherBrowserAgent::BrowserShutdownHelper::BrowserShutdownHelper(
+    Browser* browser,
+    WebStateListObserver* web_state_list_observer)
+    : web_state_list_observer_(web_state_list_observer) {
+  DCHECK(browser);
+  DCHECK(web_state_list_observer_);
+  scoped_observer_.Add(browser);
+  browser->GetWebStateList()->AddObserver(web_state_list_observer_);
+}
+
+AppLauncherBrowserAgent::BrowserShutdownHelper::~BrowserShutdownHelper() {
+  // The WebStateListObserver must be detached before destruction.
+  DCHECK(!web_state_list_observer_);
+}
+
+#pragma mark BrowserObserver
+
+void AppLauncherBrowserAgent::BrowserShutdownHelper::BrowserDestroyed(
+    Browser* browser) {
+  scoped_observer_.Remove(browser);
+  browser->GetWebStateList()->RemoveObserver(web_state_list_observer_);
+  web_state_list_observer_ = nullptr;
+}
diff --git a/ios/chrome/browser/app_launcher/app_launcher_browser_agent_unittest.mm b/ios/chrome/browser/app_launcher/app_launcher_browser_agent_unittest.mm
new file mode 100644
index 0000000..4c5e62c
--- /dev/null
+++ b/ios/chrome/browser/app_launcher/app_launcher_browser_agent_unittest.mm
@@ -0,0 +1,258 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/app_launcher/app_launcher_browser_agent.h"
+
+#import <UIKit/UIKit.h>
+#include <map>
+
+#include "base/test/task_environment.h"
+#import "ios/chrome/browser/app_launcher/app_launcher_tab_helper.h"
+#import "ios/chrome/browser/app_launcher/fake_app_launcher_abuse_detector.h"
+#include "ios/chrome/browser/main/test_browser.h"
+#include "ios/chrome/browser/overlays/public/overlay_callback_manager.h"
+#include "ios/chrome/browser/overlays/public/overlay_request.h"
+#import "ios/chrome/browser/overlays/public/overlay_request_queue.h"
+#include "ios/chrome/browser/overlays/public/overlay_response.h"
+#import "ios/chrome/browser/overlays/public/web_content_area/app_launcher_alert_overlay.h"
+#import "ios/chrome/browser/web_state_list/web_state_list.h"
+#import "ios/chrome/browser/web_state_list/web_state_opener.h"
+#import "ios/web/public/test/fakes/test_navigation_manager.h"
+#import "ios/web/public/test/fakes/test_web_state.h"
+#import "net/base/mac/url_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#include "url/gurl.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// Test fixture for AppLauncherBrowserAgent.
+class AppLauncherBrowserAgentTest : public PlatformTest {
+ protected:
+  AppLauncherBrowserAgentTest() {
+    AppLauncherBrowserAgent::CreateForBrowser(&browser_);
+    application_ = OCMClassMock([UIApplication class]);
+    OCMStub([application_ sharedApplication]).andReturn(application_);
+  }
+  ~AppLauncherBrowserAgentTest() override {
+    [application_ stopMocking];
+    browser_.GetWebStateList()->CloseAllWebStates(WebStateList::CLOSE_NO_FLAGS);
+  }
+
+  // Returns the AppLauncherBrowserAgent.
+  AppLauncherBrowserAgent* browser_agent() {
+    return AppLauncherBrowserAgent::FromBrowser(&browser_);
+  }
+
+  // Adds a WebState to |browser_| using |opener|.  The WebState's session
+  // history is populated with |nav_item_count| items.  Returns the added
+  // WebState.
+  web::WebState* AddWebState(web::WebState* opener, size_t nav_item_count) {
+    // Create the NavigationManager and populate it with |nav_item_count| items.
+    std::unique_ptr<web::TestNavigationManager> navigation_manager =
+        std::make_unique<web::TestNavigationManager>();
+    for (size_t i = 0; i < nav_item_count; ++i) {
+      navigation_manager->AddItem(GURL("http://www.chromium.test"),
+                                  ui::PAGE_TRANSITION_LINK);
+    }
+    // Create the WebState with the fake NavigationManager.
+    std::unique_ptr<web::TestWebState> passed_web_state =
+        std::make_unique<web::TestWebState>();
+    web::TestWebState* web_state = passed_web_state.get();
+    web_state->SetNavigationManager(std::move(navigation_manager));
+    web_state->SetHasOpener(opener);
+    // Ensure that the tab helper is created.
+    FakeAppLauncherAbuseDetector* abuse_detector =
+        [[FakeAppLauncherAbuseDetector alloc] init];
+    abuse_detectors_[web_state] = abuse_detector;
+    AppLauncherTabHelper::CreateForWebState(web_state, abuse_detector);
+    // Insert the WebState into the Browser's WebStateList.
+    int index = browser_.GetWebStateList()->count();
+    browser_.GetWebStateList()->InsertWebState(
+        index, std::move(passed_web_state), WebStateList::INSERT_ACTIVATE,
+        WebStateOpener(opener));
+    return web_state;
+  }
+
+  // Returns whether the front OverlayRequest for |web_state|'s queue is
+  // configured with an AppLauncherAlertOverlayRequestConfig with
+  // |is_repeated_request|.
+  bool IsShowingDialog(web::WebState* web_state, bool is_repeated_request) {
+    OverlayRequest* request = OverlayRequestQueue::FromWebState(
+                                  web_state, OverlayModality::kWebContentArea)
+                                  ->front_request();
+    if (!request)
+      return false;
+
+    AppLauncherAlertOverlayRequestConfig* config =
+        request->GetConfig<AppLauncherAlertOverlayRequestConfig>();
+    return config && config->is_repeated_request() == is_repeated_request;
+  }
+
+  base::test::TaskEnvironment task_environment_;
+  TestBrowser browser_;
+  std::map<web::WebState*, FakeAppLauncherAbuseDetector*> abuse_detectors_;
+  id application_ = nil;
+};
+
+// Tests that the browser agent shows an alert for app store URLs.
+TEST_F(AppLauncherBrowserAgentTest, AppStoreUrlShowsAlert) {
+  const GURL kAppStoreUrl("itms://1234");
+  const GURL kSourcePageUrl("http://www.chromium.test");
+  web::WebState* web_state =
+      AddWebState(/*opener=*/nullptr, /*nav_item_count=*/1);
+
+  // Request an app launch for kAppStoreUrl.
+  AppLauncherTabHelper::FromWebState(web_state)->RequestToLaunchApp(
+      kAppStoreUrl, kSourcePageUrl, /*link_transition=*/false);
+
+  // Verify that an app launch overlay request was added to |web_state|'s queue.
+  EXPECT_TRUE(IsShowingDialog(web_state, /*is_repeated_request=*/false));
+
+  // Add a response allowing the navigation.
+  OverlayRequestQueue* queue = OverlayRequestQueue::FromWebState(
+      web_state, OverlayModality::kWebContentArea);
+  queue->front_request()->GetCallbackManager()->SetCompletionResponse(
+      OverlayResponse::CreateWithInfo<AppLauncherAlertOverlayResponseInfo>(
+          /*allow_navigation=*/true));
+
+  // Cancel requests in the queue so that the completion callback is executed,
+  // expecting that the application will open the URL.
+  OCMExpect([application_ openURL:net::NSURLWithGURL(kAppStoreUrl)
+                          options:@{}
+                completionHandler:nil]);
+  queue->CancelAllRequests();
+
+  // Verify that the application attempts to open the URL.
+  [application_ verify];
+}
+
+// Tests that the browser agent attempts to launch an external application for
+// mailto URLs.
+TEST_F(AppLauncherBrowserAgentTest, MailToUrlLaunchesApp) {
+  const GURL kMailToUrl("mailto:user@chromium.test");
+  const GURL kSourcePageUrl("http://www.chromium.test");
+  web::WebState* web_state =
+      AddWebState(/*opener=*/nullptr, /*nav_item_count=*/1);
+
+  // Request an app launch for kMailToUrl with a link transition, expecting that
+  // the application will open the URL.
+  OCMExpect([application_ openURL:net::NSURLWithGURL(kMailToUrl)
+                          options:@{}
+                completionHandler:nil]);
+  AppLauncherTabHelper::FromWebState(web_state)->RequestToLaunchApp(
+      kMailToUrl, kSourcePageUrl, /*link_transition=*/true);
+
+  // Verify that the application attempts to open the URL.
+  [application_ verify];
+}
+
+// Tests that the browser agent attempts to launch an external application for
+// app URLs.
+TEST_F(AppLauncherBrowserAgentTest, AppUrlLaunchesApp) {
+  const GURL kAppUrl("some-app://1234");
+  const GURL kSourcePageUrl("http://www.chromium.test");
+  web::WebState* web_state =
+      AddWebState(/*opener=*/nullptr, /*nav_item_count=*/1);
+
+  // Request an app launch for kAppUrl with a link transition, expecting that
+  // the application will open the URL.
+  OCMExpect([application_ openURL:net::NSURLWithGURL(kAppUrl)
+                          options:@{}
+                completionHandler:nil]);
+  AppLauncherTabHelper::FromWebState(web_state)->RequestToLaunchApp(
+      kAppUrl, kSourcePageUrl, /*link_transition=*/true);
+
+  // Verify that the application attempts to open the URL.
+  [application_ verify];
+}
+
+// Tests that the browser agent shows an alert for app URLs when the abuse
+// detector returns ExternalAppLaunchPolicyPrompt.
+TEST_F(AppLauncherBrowserAgentTest, RepeatedRequestShowsAlert) {
+  const GURL kAppUrl("some-app://1234");
+  const GURL kSourcePageUrl("http://www.chromium.test");
+  web::WebState* web_state =
+      AddWebState(/*opener=*/nullptr, /*nav_item_count=*/1);
+
+  // Request an app launch for kAppUrl while the abuse detector returns
+  // ExternalAppLaunchPolicyPrompt.
+  abuse_detectors_[web_state].policy = ExternalAppLaunchPolicyPrompt;
+  AppLauncherTabHelper::FromWebState(web_state)->RequestToLaunchApp(
+      kAppUrl, kSourcePageUrl, /*link_transition=*/false);
+
+  // Verify that an app launch overlay request for a repeated request was added
+  // to |web_state|'s queue.
+  EXPECT_TRUE(IsShowingDialog(web_state, /*is_repeated_request=*/true));
+
+  // Add a response allowing the navigation.
+  OverlayRequestQueue* queue = OverlayRequestQueue::FromWebState(
+      web_state, OverlayModality::kWebContentArea);
+  queue->front_request()->GetCallbackManager()->SetCompletionResponse(
+      OverlayResponse::CreateWithInfo<AppLauncherAlertOverlayResponseInfo>(
+          /*allow_navigation=*/true));
+
+  // Cancel requests in the queue so that the completion callback is executed,
+  // expecting that the application will open the URL.
+  OCMExpect([application_ openURL:net::NSURLWithGURL(kAppUrl)
+                          options:@{}
+                completionHandler:nil]);
+  queue->CancelAllRequests();
+
+  // Verify that the application attempts to open the URL.
+  [application_ verify];
+}
+
+// Tests that the browser agent shows an alert for app URLs without a link
+// transition.
+TEST_F(AppLauncherBrowserAgentTest, AppUrlWithoutLinkShowsAlert) {
+  const GURL kAppUrl("some-app://1234");
+  const GURL kSourcePageUrl("http://www.chromium.test");
+  web::WebState* web_state =
+      AddWebState(/*opener=*/nullptr, /*nav_item_count=*/1);
+
+  // Request an app launch for kAppUrl without a link transition.
+  AppLauncherTabHelper::FromWebState(web_state)->RequestToLaunchApp(
+      kAppUrl, kSourcePageUrl, /*link_transition=*/false);
+
+  // Verify that an app launch overlay request was added to |web_state|'s queue.
+  EXPECT_TRUE(IsShowingDialog(web_state, /*is_repeated_request=*/false));
+
+  // Add a response allowing the navigation.
+  OverlayRequestQueue* queue = OverlayRequestQueue::FromWebState(
+      web_state, OverlayModality::kWebContentArea);
+  queue->front_request()->GetCallbackManager()->SetCompletionResponse(
+      OverlayResponse::CreateWithInfo<AppLauncherAlertOverlayResponseInfo>(
+          /*allow_navigation=*/true));
+
+  // Cancel requests in the queue so that the completion callback is executed,
+  // expecting that the application will open the URL.
+  OCMExpect([application_ openURL:net::NSURLWithGURL(kAppUrl)
+                          options:@{}
+                completionHandler:nil]);
+  queue->CancelAllRequests();
+
+  // Verify that the application attempts to open the URL.
+  [application_ verify];
+}
+
+// Tests that the browser agent shows a dialog in the opener's
+// OverlayRequestQueue if an app launch is requested for a WebState with an
+// empty session history.
+TEST_F(AppLauncherBrowserAgentTest, ShowDialogInOpener) {
+  const GURL kAppStoreUrl("itms://1234");
+  const GURL kSourcePageUrl("http://www.chromium.test");
+  web::WebState* opener = AddWebState(/*opener=*/nullptr, /*nav_item_count=*/1);
+  web::WebState* web_state = AddWebState(opener, /*nav_item_count=*/0);
+
+  // Request an app launch for kAppStoreUrl.
+  AppLauncherTabHelper::FromWebState(web_state)->RequestToLaunchApp(
+      kAppStoreUrl, kSourcePageUrl, /*link_transition=*/false);
+
+  // Verify that an app launch overlay request was added to |web_state|'s queue.
+  EXPECT_TRUE(IsShowingDialog(opener, /*is_repeated_request=*/false));
+}
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.h b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.h
index 7c8643f7..d4d17b0 100644
--- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.h
+++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.h
@@ -6,10 +6,11 @@
 #define IOS_CHROME_BROWSER_APP_LAUNCHER_APP_LAUNCHER_TAB_HELPER_H_
 
 #include "base/macros.h"
+#import "ios/chrome/browser/app_launcher/app_launcher_abuse_detector.h"
 #import "ios/web/public/navigation/web_state_policy_decider.h"
 #import "ios/web/public/web_state_user_data.h"
 
-@protocol AppLauncherTabHelperDelegate;
+class AppLauncherTabHelperDelegate;
 @class AppLauncherAbuseDetector;
 class GURL;
 
@@ -20,28 +21,27 @@
  public:
   ~AppLauncherTabHelper() override;
 
-  // Creates AppLauncherTabHelper and attaches to |web_state|. |web_state| must
-  // not be null. |policy_decider| provides policy for launching apps.
-  // |delegate| can launch applications and present UI and is not retained by
-  // TabHelper.
+  // Creates a tab helper for |web_state| that uses |abuse_detector| to make
+  // navigation policy decisions.
   static void CreateForWebState(web::WebState* web_state,
-                                AppLauncherAbuseDetector* abuse_detector,
-                                id<AppLauncherTabHelperDelegate> delegate);
+                                AppLauncherAbuseDetector* abuse_detector =
+                                    [[AppLauncherAbuseDetector alloc] init]);
 
   // Returns true, if the |url| has a scheme for an external application
   // (eg. twitter:// , calshow://).
   static bool IsAppUrl(const GURL& url);
 
+  // Sets the delegate.
+  void SetDelegate(AppLauncherTabHelperDelegate* delegate);
+
   // Requests to open the application with |url|.
   // The method checks if the application for |url| has been opened repeatedly
   // by the |source_page_url| page in a short time frame, in that case a prompt
   // will appear to the user with an option to block the application from
   // launching. Then the method also checks for user interaction and for schemes
   // that require special handling (eg. facetime, mailto) and may present the
-  // user with a confirmation dialog to open the application. If there is no
-  // such application available or it's not possible to open the application the
-  // method returns NO.
-  bool RequestToLaunchApp(const GURL& url,
+  // user with a confirmation dialog to open the application.
+  void RequestToLaunchApp(const GURL& url,
                           const GURL& source_page_url,
                           bool link_transition);
 
@@ -54,11 +54,12 @@
   friend class web::WebStateUserData<AppLauncherTabHelper>;
 
   // Constructor for AppLauncherTabHelper. |abuse_detector| provides policy for
-  // launching apps. |delegate| can launch applications and present UI and is
-  // not retained by TabHelper.
+  // launching apps.
   AppLauncherTabHelper(web::WebState* web_state,
-                       AppLauncherAbuseDetector* abuse_detector,
-                       id<AppLauncherTabHelperDelegate> delegate);
+                       AppLauncherAbuseDetector* abuse_detector);
+
+  // Getter for the delegate.
+  AppLauncherTabHelperDelegate* delegate() const { return delegate_; }
 
   // The WebState that this object is attached to.
   web::WebState* web_state_ = nullptr;
@@ -67,13 +68,13 @@
   AppLauncherAbuseDetector* abuse_detector_ = nil;
 
   // Used to launch apps and present UI.
-  __weak id<AppLauncherTabHelperDelegate> delegate_ = nil;
+  AppLauncherTabHelperDelegate* delegate_ = nullptr;
 
   // Returns whether there is a prompt shown by |RequestToOpenUrl| or not.
   bool is_prompt_active_ = false;
 
   // Must be last member to ensure it is destroyed last.
-  base::WeakPtrFactory<AppLauncherTabHelper> weak_factory_;
+  base::WeakPtrFactory<AppLauncherTabHelper> weak_factory_{this};
 
   WEB_STATE_USER_DATA_KEY_DECL();
 
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm
index 295479e64..8c082be 100644
--- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm
+++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper.mm
@@ -10,13 +10,11 @@
 #include "base/metrics/histogram_macros.h"
 #import "base/strings/sys_string_conversions.h"
 #include "components/reading_list/core/reading_list_model.h"
-#import "ios/chrome/browser/app_launcher/app_launcher_abuse_detector.h"
 #import "ios/chrome/browser/app_launcher/app_launcher_tab_helper_delegate.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/chrome_url_util.h"
 #include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
 #import "ios/chrome/browser/u2f/u2f_tab_helper.h"
-#import "ios/chrome/browser/ui/dialogs/dialog_features.h"
 #import "ios/web/common/url_scheme_util.h"
 #import "ios/web/public/navigation/navigation_item.h"
 #import "ios/web/public/navigation/navigation_manager.h"
@@ -71,27 +69,26 @@
 
 }  // namespace
 
+// static
 void AppLauncherTabHelper::CreateForWebState(
     web::WebState* web_state,
-    AppLauncherAbuseDetector* abuse_detector,
-    id<AppLauncherTabHelperDelegate> delegate) {
-  DCHECK(web_state);
-  if (!FromWebState(web_state)) {
-    web_state->SetUserData(UserDataKey(),
-                           base::WrapUnique(new AppLauncherTabHelper(
-                               web_state, abuse_detector, delegate)));
-  }
+    AppLauncherAbuseDetector* abuse_detector) {
+  if (FromWebState(web_state))
+    return;
+
+  web_state->SetUserData(
+      UserDataKey(),
+      base::WrapUnique(new AppLauncherTabHelper(web_state, abuse_detector)));
 }
 
 AppLauncherTabHelper::AppLauncherTabHelper(
     web::WebState* web_state,
-    AppLauncherAbuseDetector* abuse_detector,
-    id<AppLauncherTabHelperDelegate> delegate)
+    AppLauncherAbuseDetector* abuse_detector)
     : web::WebStatePolicyDecider(web_state),
       web_state_(web_state),
-      abuse_detector_(abuse_detector),
-      delegate_(delegate),
-      weak_factory_(this) {}
+      abuse_detector_(abuse_detector) {
+  DCHECK(abuse_detector_);
+}
 
 AppLauncherTabHelper::~AppLauncherTabHelper() = default;
 
@@ -103,18 +100,22 @@
            url.SchemeIs(url::kBlobScheme));
 }
 
-bool AppLauncherTabHelper::RequestToLaunchApp(const GURL& url,
+void AppLauncherTabHelper::SetDelegate(AppLauncherTabHelperDelegate* delegate) {
+  delegate_ = delegate;
+}
+
+void AppLauncherTabHelper::RequestToLaunchApp(const GURL& url,
                                               const GURL& source_page_url,
                                               bool link_transition) {
   // Don't open external application if chrome is not active.
   if ([[UIApplication sharedApplication] applicationState] !=
       UIApplicationStateActive) {
-    return false;
+    return;
   }
 
   // Don't try to open external application if a prompt is already active.
   if (is_prompt_active_)
-    return false;
+    return;
 
   [abuse_detector_ didRequestLaunchExternalAppURL:url
                                 fromSourcePageURL:source_page_url];
@@ -123,12 +124,12 @@
                         fromSourcePageURL:source_page_url];
   switch (policy) {
     case ExternalAppLaunchPolicyBlock: {
-      return false;
+      return;
     }
     case ExternalAppLaunchPolicyAllow: {
-      return [delegate_ appLauncherTabHelper:this
-                            launchAppWithURL:url
-                              linkTransition:link_transition];
+      if (delegate_)
+        delegate_->LaunchAppForTabHelper(this, url, link_transition);
+      return;
     }
     case ExternalAppLaunchPolicyPrompt: {
       is_prompt_active_ = true;
@@ -136,29 +137,22 @@
           weak_factory_.GetWeakPtr();
       GURL copied_url = url;
       GURL copied_source_page_url = source_page_url;
-      [delegate_ appLauncherTabHelper:this
-          showAlertOfRepeatedLaunchesWithCompletionHandler:^(
-              BOOL user_allowed) {
+      if (!delegate_)
+        return;
+      delegate_->ShowRepeatedAppLaunchAlert(
+          this, base::BindOnce(^(BOOL user_allowed) {
             if (!weak_this.get())
               return;
-            if (user_allowed) {
+            if (user_allowed && weak_this->delegate()) {
               // By confirming that user wants to launch the application, there
               // is no need to check for |link_tapped|.
-              [delegate_ appLauncherTabHelper:weak_this.get()
-                             launchAppWithURL:copied_url
-                               linkTransition:YES];
-            } else {
-              if (!base::FeatureList::IsEnabled(dialogs::kNonModalDialogs)) {
-                // Only block app launches if the app launch alert is being
-                // displayed modally since DOS attacks are not possible when the
-                // app launch alert is presented non-modally.
-                [abuse_detector_ blockLaunchingAppURL:copied_url
-                                    fromSourcePageURL:copied_source_page_url];
-              }
+              weak_this->delegate()->LaunchAppForTabHelper(
+                  this, copied_url,
+                  /*link_transition=*/true);
             }
             is_prompt_active_ = false;
-          }];
-      return true;
+          }));
+      return;
     }
   }
 }
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_delegate.h b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_delegate.h
index b2f3989..5effa12 100644
--- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_delegate.h
+++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_delegate.h
@@ -5,29 +5,29 @@
 #ifndef IOS_CHROME_BROWSER_APP_LAUNCHER_APP_LAUNCHER_TAB_HELPER_DELEGATE_H_
 #define IOS_CHROME_BROWSER_APP_LAUNCHER_APP_LAUNCHER_TAB_HELPER_DELEGATE_H_
 
-#include "ios/chrome/browser/procedural_block_types.h"
+#include "base/callback.h"
 
 class AppLauncherTabHelper;
 class GURL;
 
-// Protocol for handling application launching and presenting related UI.
-@protocol AppLauncherTabHelperDelegate
+// Interface for handling application launching from a tab helper.
+class AppLauncherTabHelperDelegate {
+ public:
+  AppLauncherTabHelperDelegate() = default;
+  virtual ~AppLauncherTabHelperDelegate() = default;
 
-// Launches application that has |URL| if possible (optionally after confirming
-// via dialog). Returns NO if there is no such application available.
-// TODO(crbug.com/850760): Change this method return to void, once the new
-// AppLauncherRefresh logic is always enabled.
-- (BOOL)appLauncherTabHelper:(AppLauncherTabHelper*)tabHelper
-            launchAppWithURL:(const GURL&)URL
-              linkTransition:(BOOL)linkTransition;
+  // Launches application that has |URL| if possible (optionally after
+  // confirming via dialog).
+  virtual void LaunchAppForTabHelper(AppLauncherTabHelper* tab_helper,
+                                     const GURL& url,
+                                     bool link_transition) = 0;
 
-// Alerts the user that there have been repeated attempts to launch
-// the application. |completionHandler| is called with the user's
-// response on whether to launch the application.
-- (void)appLauncherTabHelper:(AppLauncherTabHelper*)tabHelper
-    showAlertOfRepeatedLaunchesWithCompletionHandler:
-        (ProceduralBlockWithBool)completionHandler;
-
-@end
+  // Alerts the user that there have been repeated attempts to launch
+  // the application. |completionHandler| is called with the user's
+  // response on whether to launch the application.
+  virtual void ShowRepeatedAppLaunchAlert(
+      AppLauncherTabHelper* tab_helper,
+      base::OnceCallback<void(bool)> completion) = 0;
+};
 
 #endif  // IOS_CHROME_BROWSER_APP_LAUNCHER_APP_LAUNCHER_TAB_HELPER_DELEGATE_H_
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm
index 14086b9..fec1298a 100644
--- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm
+++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm
@@ -12,8 +12,8 @@
 #include "base/time/default_clock.h"
 #include "components/reading_list/core/reading_list_entry.h"
 #include "components/reading_list/core/reading_list_model_impl.h"
-#import "ios/chrome/browser/app_launcher/app_launcher_abuse_detector.h"
 #import "ios/chrome/browser/app_launcher/app_launcher_tab_helper_delegate.h"
+#import "ios/chrome/browser/app_launcher/fake_app_launcher_abuse_detector.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #import "ios/chrome/browser/chrome_url_util.h"
 #include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
@@ -30,56 +30,43 @@
 #error "This file requires ARC support."
 #endif
 
-// An object that conforms to AppLauncherTabHelperDelegate for testing.
-@interface FakeAppLauncherTabHelperDelegate
-    : NSObject<AppLauncherTabHelperDelegate>
-// URL of the last launched application.
-@property(nonatomic, assign) GURL lastLaunchedAppURL;
-// Number of times an app was launched.
-@property(nonatomic, assign) NSUInteger countOfAppsLaunched;
-// Number of times the repeated launches alert has been shown.
-@property(nonatomic, assign) NSUInteger countOfAlertsShown;
-// Simulates the user tapping the accept button when prompted via
-// |-appLauncherTabHelper:showAlertOfRepeatedLaunchesWithCompletionHandler|.
-@property(nonatomic, assign) BOOL simulateUserAcceptingPrompt;
-@end
-
-@implementation FakeAppLauncherTabHelperDelegate
-@synthesize lastLaunchedAppURL = _lastLaunchedAppURL;
-@synthesize countOfAppsLaunched = _countOfAppsLaunched;
-@synthesize countOfAlertsShown = _countOfAlertsShown;
-@synthesize simulateUserAcceptingPrompt = _simulateUserAcceptingPrompt;
-
-- (BOOL)appLauncherTabHelper:(AppLauncherTabHelper*)tabHelper
-            launchAppWithURL:(const GURL&)URL
-              linkTransition:(BOOL)linkTransition {
-  self.countOfAppsLaunched++;
-  self.lastLaunchedAppURL = URL;
-  return YES;
-}
-
-- (void)appLauncherTabHelper:(AppLauncherTabHelper*)tabHelper
-    showAlertOfRepeatedLaunchesWithCompletionHandler:
-        (ProceduralBlockWithBool)completionHandler {
-  self.countOfAlertsShown++;
-  completionHandler(self.simulateUserAcceptingPrompt);
-}
-@end
-
-// An AppLauncherAbuseDetector for testing.
-@interface FakeAppLauncherAbuseDetector : AppLauncherAbuseDetector
-@property(nonatomic, assign) ExternalAppLaunchPolicy policy;
-@end
-
-@implementation FakeAppLauncherAbuseDetector
-@synthesize policy = _policy;
-- (ExternalAppLaunchPolicy)launchPolicyForURL:(const GURL&)URL
-                            fromSourcePageURL:(const GURL&)sourcePageURL {
-  return self.policy;
-}
-@end
-
 namespace {
+// An fake AppLauncherTabHelperDelegate for tests.
+class FakeAppLauncherTabHelperDelegate : public AppLauncherTabHelperDelegate {
+ public:
+  GURL last_launched_app_url() { return last_launched_app_url_; }
+  size_t app_launch_count() { return app_launch_count_; }
+  size_t alert_shown_count() { return alert_shown_count_; }
+  void set_should_accept_prompt(bool should_accept_prompt) {
+    should_accept_prompt_ = should_accept_prompt;
+  }
+  bool should_accept_prompt() { return should_accept_prompt_; }
+
+  // AppLauncherTabHelperDelegate:
+  void LaunchAppForTabHelper(AppLauncherTabHelper* tab_helper,
+                             const GURL& url,
+                             bool link_transition) override {
+    ++app_launch_count_;
+    last_launched_app_url_ = url;
+  }
+  void ShowRepeatedAppLaunchAlert(
+      AppLauncherTabHelper* tab_helper,
+      base::OnceCallback<void(bool)> completion) override {
+    ++alert_shown_count_;
+    std::move(completion).Run(should_accept_prompt_);
+  }
+
+ private:
+  // URL of the last launched application.
+  GURL last_launched_app_url_;
+  // Number of times an app was launched.
+  size_t app_launch_count_ = 0;
+  // Number of times the repeated launches alert has been shown.
+  size_t alert_shown_count_ = 0;
+  // Simulates the user tapping the accept button when prompted via
+  // |-appLauncherTabHelper:showAlertOfRepeatedLaunchesWithCompletionHandler|.
+  bool should_accept_prompt_ = false;
+};
 // A fake NavigationManager to be used by the WebState object for the
 // AppLauncher.
 class FakeNavigationManager : public web::TestNavigationManager {
@@ -101,15 +88,14 @@
                                base::DefaultClock::GetInstance()));
   return reading_list_model;
 }
+}  // namespace
 
 // Test fixture for AppLauncherTabHelper class.
 class AppLauncherTabHelperTest : public PlatformTest {
  protected:
   AppLauncherTabHelperTest()
-      : abuse_detector_([[FakeAppLauncherAbuseDetector alloc] init]),
-        delegate_([[FakeAppLauncherTabHelperDelegate alloc] init]) {
-    AppLauncherTabHelper::CreateForWebState(&web_state_, abuse_detector_,
-                                            delegate_);
+      : abuse_detector_([[FakeAppLauncherAbuseDetector alloc] init]) {
+    AppLauncherTabHelper::CreateForWebState(&web_state_, abuse_detector_);
     U2FTabHelper::CreateForWebState(&web_state_);
     // Allow is the default policy for this test.
     abuse_detector_.policy = ExternalAppLaunchPolicyAllow;
@@ -118,6 +104,7 @@
     web_state_.SetNavigationManager(std::move(navigation_manager));
     web_state_.SetCurrentURL(GURL("https://chromium.org"));
     tab_helper_ = AppLauncherTabHelper::FromWebState(&web_state_);
+    tab_helper_->SetDelegate(&delegate_);
   }
 
   bool TestShouldAllowRequest(NSString* url_string,
@@ -189,9 +176,9 @@
 
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state_ = nil;
   FakeAppLauncherAbuseDetector* abuse_detector_ = nil;
-  FakeAppLauncherTabHelperDelegate* delegate_ = nil;
+  FakeAppLauncherTabHelperDelegate delegate_;
   bool is_reading_list_initialized_ = false;
-  AppLauncherTabHelper* tab_helper_;
+  AppLauncherTabHelper* tab_helper_ = nullptr;
 };
 
 // Tests that a valid URL launches app.
@@ -200,8 +187,8 @@
   EXPECT_FALSE(TestShouldAllowRequest(@"valid://1234",
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(1U, delegate_.countOfAppsLaunched);
-  EXPECT_EQ(GURL("valid://1234"), delegate_.lastLaunchedAppURL);
+  EXPECT_EQ(1U, delegate_.app_launch_count());
+  EXPECT_EQ(GURL("valid://1234"), delegate_.last_launched_app_url());
 }
 
 // Tests that a valid URL does not launch app when launch policy is to block.
@@ -210,33 +197,32 @@
   EXPECT_FALSE(TestShouldAllowRequest(@"valid://1234",
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(0U, delegate_.countOfAlertsShown);
-  EXPECT_EQ(0U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(0U, delegate_.alert_shown_count());
+  EXPECT_EQ(0U, delegate_.app_launch_count());
 }
 
 // Tests that a valid URL shows an alert and launches app when launch policy is
 // to prompt and user accepts.
 TEST_F(AppLauncherTabHelperTest, ValidUrlPromptUserAccepts) {
   abuse_detector_.policy = ExternalAppLaunchPolicyPrompt;
-  delegate_.simulateUserAcceptingPrompt = YES;
+  delegate_.set_should_accept_prompt(true);
   EXPECT_FALSE(TestShouldAllowRequest(@"valid://1234",
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
 
-  EXPECT_EQ(1U, delegate_.countOfAlertsShown);
-  EXPECT_EQ(1U, delegate_.countOfAppsLaunched);
-  EXPECT_EQ(GURL("valid://1234"), delegate_.lastLaunchedAppURL);
+  EXPECT_EQ(1U, delegate_.alert_shown_count());
+  EXPECT_EQ(1U, delegate_.app_launch_count());
+  EXPECT_EQ(GURL("valid://1234"), delegate_.last_launched_app_url());
 }
 
 // Tests that a valid URL does not launch app when launch policy is to prompt
 // and user rejects.
 TEST_F(AppLauncherTabHelperTest, ValidUrlPromptUserRejects) {
   abuse_detector_.policy = ExternalAppLaunchPolicyPrompt;
-  delegate_.simulateUserAcceptingPrompt = NO;
   EXPECT_FALSE(TestShouldAllowRequest(@"valid://1234",
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(0U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(0U, delegate_.app_launch_count());
 }
 
 // Tests that ShouldAllowRequest only launches apps for App Urls in main frame,
@@ -245,21 +231,21 @@
   NSString* url_string = @"itms-apps://itunes.apple.com/us/app/appname/id123";
   EXPECT_FALSE(TestShouldAllowRequest(url_string, /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(1U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(1U, delegate_.app_launch_count());
 
   EXPECT_FALSE(TestShouldAllowRequest(url_string, /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/true));
-  EXPECT_EQ(2U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(2U, delegate_.app_launch_count());
 
   EXPECT_FALSE(TestShouldAllowRequest(url_string,
                                       /*target_frame_is_main=*/false,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(2U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(2U, delegate_.app_launch_count());
 
   EXPECT_FALSE(TestShouldAllowRequest(url_string,
                                       /*target_frame_is_main=*/false,
                                       /*has_user_gesture=*/true));
-  EXPECT_EQ(3U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(3U, delegate_.app_launch_count());
 }
 
 // Tests that ShouldAllowRequest always allows requests and does not launch
@@ -280,7 +266,7 @@
   EXPECT_TRUE(TestShouldAllowRequest(@"blob://test",
                                      /*target_frame_is_main=*/false,
                                      /*has_user_gesture=*/true));
-  EXPECT_EQ(0U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(0U, delegate_.app_launch_count());
 }
 
 // Tests that invalid Urls are completely blocked.
@@ -291,7 +277,7 @@
   EXPECT_FALSE(TestShouldAllowRequest(@"invalid",
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(0U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(0U, delegate_.app_launch_count());
 }
 
 // Tests that when the last committed URL is invalid, the URL is only opened
@@ -307,13 +293,13 @@
   EXPECT_FALSE(TestShouldAllowRequest(url_string,
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(0U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(0U, delegate_.app_launch_count());
 
   navigation_manager_->SetLastCommittedItem(nullptr);
   EXPECT_FALSE(TestShouldAllowRequest(url_string,
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(1U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(1U, delegate_.app_launch_count());
 }
 
 // Tests that URLs with schemes that might be a security risk are blocked.
@@ -321,7 +307,7 @@
   EXPECT_FALSE(TestShouldAllowRequest(@"app-settings://",
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(0U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(0U, delegate_.app_launch_count());
 }
 
 // Tests that URLs with U2F schemes are handled correctly.
@@ -341,7 +327,7 @@
   EXPECT_FALSE(TestShouldAllowRequest(@"u2f-x-callback://chromium.test",
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(0U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(0U, delegate_.app_launch_count());
 
   // Source URL is not trusted, so u2f scheme should not be allowed.
   item->SetURL(GURL("https://chromium.test"));
@@ -349,7 +335,7 @@
   EXPECT_FALSE(TestShouldAllowRequest(@"u2f://chromium.test",
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(0U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(0U, delegate_.app_launch_count());
 
   // Source URL is trusted, so u2f scheme should be allowed and an external app
   // is launched via URL with u2f-x-callback scheme.
@@ -358,8 +344,8 @@
   EXPECT_FALSE(TestShouldAllowRequest(@"u2f://chromium.test",
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(1U, delegate_.countOfAppsLaunched);
-  EXPECT_TRUE(delegate_.lastLaunchedAppURL.SchemeIs("u2f-x-callback"));
+  EXPECT_EQ(1U, delegate_.app_launch_count());
+  EXPECT_TRUE(delegate_.last_launched_app_url().SchemeIs("u2f-x-callback"));
 }
 
 // Tests that URLs with Chrome Bundle schemes are blocked on iframes.
@@ -370,18 +356,18 @@
   EXPECT_FALSE(TestShouldAllowRequest(url,
                                       /*target_frame_is_main=*/false,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(0U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(0U, delegate_.app_launch_count());
 
   EXPECT_FALSE(TestShouldAllowRequest(url,
                                       /*target_frame_is_main=*/false,
                                       /*has_user_gesture=*/true));
-  EXPECT_EQ(0U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(0U, delegate_.app_launch_count());
 
   // Chrome Bundle URL scheme is only allowed from main frames.
   EXPECT_FALSE(TestShouldAllowRequest(url,
                                       /*target_frame_is_main=*/true,
                                       /*has_user_gesture=*/false));
-  EXPECT_EQ(1U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(1U, delegate_.app_launch_count());
 }
 
 // Tests that ShouldAllowRequest updates the reading list correctly for non-link
@@ -392,23 +378,23 @@
   EXPECT_TRUE(TestReadingListUpdate(/*is_app_blocked=*/true,
                                     /*is_link_transition*/ false,
                                     /*expected_read_status*/ true));
-  EXPECT_EQ(0U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(0U, delegate_.app_launch_count());
 
   EXPECT_TRUE(TestReadingListUpdate(/*is_app_blocked=*/false,
                                     /*is_link_transition*/ false,
                                     /*expected_read_status*/ true));
-  EXPECT_EQ(1U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(1U, delegate_.app_launch_count());
 
   // Don't update reading list if the transition is a link transition.
   EXPECT_TRUE(TestReadingListUpdate(/*is_app_blocked=*/true,
                                     /*is_link_transition*/ true,
                                     /*expected_read_status*/ false));
-  EXPECT_EQ(1U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(1U, delegate_.app_launch_count());
 
   EXPECT_TRUE(TestReadingListUpdate(/*is_app_blocked=*/false,
                                     /*is_link_transition*/ true,
                                     /*expected_read_status*/ false));
-  EXPECT_EQ(2U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(2U, delegate_.app_launch_count());
 }
 
 // Tests that launching a SMS URL via a JavaScript redirect in the main frame
@@ -421,7 +407,5 @@
   EXPECT_FALSE(
       TestShouldAllowRequest(sms_url_string, /*target_frame_is_main=*/true,
                              /*has_user_gesture=*/false, page_transition));
-  EXPECT_EQ(1U, delegate_.countOfAppsLaunched);
+  EXPECT_EQ(1U, delegate_.app_launch_count());
 }
-
-}  // namespace
diff --git a/ios/chrome/browser/ui/app_launcher/app_launcher_util.h b/ios/chrome/browser/app_launcher/app_launcher_util.h
similarity index 68%
rename from ios/chrome/browser/ui/app_launcher/app_launcher_util.h
rename to ios/chrome/browser/app_launcher/app_launcher_util.h
index 52d7049..ab8519d 100644
--- a/ios/chrome/browser/ui/app_launcher/app_launcher_util.h
+++ b/ios/chrome/browser/app_launcher/app_launcher_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_UI_APP_LAUNCHER_APP_LAUNCHER_UTIL_H_
-#define IOS_CHROME_BROWSER_UI_APP_LAUNCHER_APP_LAUNCHER_UTIL_H_
+#ifndef IOS_CHROME_BROWSER_APP_LAUNCHER_APP_LAUNCHER_UTIL_H_
+#define IOS_CHROME_BROWSER_APP_LAUNCHER_APP_LAUNCHER_UTIL_H_
 
 #import <Foundation/Foundation.h>
 
@@ -15,4 +15,4 @@
 // Returns whether |url| has an app store scheme.
 bool UrlHasAppStoreScheme(const GURL& url);
 
-#endif  // IOS_CHROME_BROWSER_UI_APP_LAUNCHER_APP_LAUNCHER_UTIL_H_
+#endif  // IOS_CHROME_BROWSER_APP_LAUNCHER_APP_LAUNCHER_UTIL_H_
diff --git a/ios/chrome/browser/ui/app_launcher/app_launcher_util.mm b/ios/chrome/browser/app_launcher/app_launcher_util.mm
similarity index 87%
rename from ios/chrome/browser/ui/app_launcher/app_launcher_util.mm
rename to ios/chrome/browser/app_launcher/app_launcher_util.mm
index 0116f0e..59264ba 100644
--- a/ios/chrome/browser/ui/app_launcher/app_launcher_util.mm
+++ b/ios/chrome/browser/app_launcher/app_launcher_util.mm
@@ -2,11 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/ui/app_launcher/app_launcher_util.h"
+#import "ios/chrome/browser/app_launcher/app_launcher_util.h"
 
 #include "base/strings/sys_string_conversions.h"
-#include "ios/chrome/grit/ios_strings.h"
-#include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/app_launcher/fake_app_launcher_abuse_detector.h b/ios/chrome/browser/app_launcher/fake_app_launcher_abuse_detector.h
new file mode 100644
index 0000000..f937ec57
--- /dev/null
+++ b/ios/chrome/browser/app_launcher/fake_app_launcher_abuse_detector.h
@@ -0,0 +1,19 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_APP_LAUNCHER_FAKE_APP_LAUNCHER_ABUSE_DETECTOR_H_
+#define IOS_CHROME_BROWSER_APP_LAUNCHER_FAKE_APP_LAUNCHER_ABUSE_DETECTOR_H_
+
+#import "ios/chrome/browser/app_launcher/app_launcher_abuse_detector.h"
+
+// An AppLauncherAbuseDetector for testing.
+@interface FakeAppLauncherAbuseDetector : AppLauncherAbuseDetector
+
+// The policy returned by |-launchPolicyforURL:fromSourcePageURL:|.  Default
+// value is ExternalAppLaunchPolicyAllow.
+@property(nonatomic, assign) ExternalAppLaunchPolicy policy;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_APP_LAUNCHER_FAKE_APP_LAUNCHER_ABUSE_DETECTOR_H_
diff --git a/ios/chrome/browser/app_launcher/fake_app_launcher_abuse_detector.mm b/ios/chrome/browser/app_launcher/fake_app_launcher_abuse_detector.mm
new file mode 100644
index 0000000..880713c
--- /dev/null
+++ b/ios/chrome/browser/app_launcher/fake_app_launcher_abuse_detector.mm
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/app_launcher/fake_app_launcher_abuse_detector.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@implementation FakeAppLauncherAbuseDetector
+
+- (instancetype)init {
+  if (self = [super init]) {
+    _policy = ExternalAppLaunchPolicyAllow;
+  }
+  return self;
+}
+
+- (ExternalAppLaunchPolicy)launchPolicyForURL:(const GURL&)URL
+                            fromSourcePageURL:(const GURL&)sourcePageURL {
+  return self.policy;
+}
+@end
diff --git a/ios/chrome/browser/chrome_switches.h b/ios/chrome/browser/chrome_switches.h
index 23960c4..7e82fc444 100644
--- a/ios/chrome/browser/chrome_switches.h
+++ b/ios/chrome/browser/chrome_switches.h
@@ -10,12 +10,10 @@
 namespace switches {
 
 extern const char kDisableIOSPasswordSuggestions[];
-extern const char kDisableNTPFavicons[];
 extern const char kDisableThirdPartyKeyboardWorkaround[];
 
 extern const char kEnableEnterprisePolicy[];
 extern const char kEnableIOSHandoffToOtherDevices[];
-extern const char kEnableNTPFavicons[];
 extern const char kEnableSpotlightActions[];
 extern const char kEnableThirdPartyKeyboardWorkaround[];
 
diff --git a/ios/chrome/browser/flags/BUILD.gn b/ios/chrome/browser/flags/BUILD.gn
index ce08bf87..9ce2e64 100644
--- a/ios/chrome/browser/flags/BUILD.gn
+++ b/ios/chrome/browser/flags/BUILD.gn
@@ -47,7 +47,6 @@
     "//ios/chrome/browser/find_in_page:feature_flags",
     "//ios/chrome/browser/passwords:feature_flags",
     "//ios/chrome/browser/ui:feature_flags",
-    "//ios/chrome/browser/ui/dialogs:feature_flags",
     "//ios/chrome/browser/ui/download:features",
     "//ios/chrome/browser/ui/fullscreen:feature_flags",
     "//ios/chrome/browser/ui/infobars:feature_flags",
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index 3fdf4b6f..cc90d7d 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -58,7 +58,6 @@
 #include "ios/chrome/browser/flags/ios_chrome_flag_descriptions.h"
 #include "ios/chrome/browser/passwords/password_manager_features.h"
 #include "ios/chrome/browser/system_flags.h"
-#import "ios/chrome/browser/ui/dialogs/dialog_features.h"
 #import "ios/chrome/browser/ui/download/features.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h"
 #import "ios/chrome/browser/ui/infobars/infobar_feature.h"
@@ -391,9 +390,6 @@
          omnibox::kUIExperimentMaxAutocompleteMatches,
          kOmniboxUIMaxAutocompleteMatchesVariations,
          "OmniboxUIMaxAutocompleteVariations")},
-    {"non-modal-dialogs", flag_descriptions::kNonModalDialogsName,
-     flag_descriptions::kNonModalDialogsDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(dialogs::kNonModalDialogs)},
     {"infobar-ui-reboot", flag_descriptions::kInfobarUIRebootName,
      flag_descriptions::kInfobarUIRebootDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kIOSInfobarUIReboot)},
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 5dd8541..dbe61df 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -286,11 +286,6 @@
     "Request the Mobile version of Google SRP by default when the desktop mode "
     "is requested by default.";
 
-const char kNonModalDialogsName[] = "Use non-modal JavaScript dialogs";
-const char kNonModalDialogsDescription[] =
-    "Presents JavaScript dialogs non-modally so that the user can change tabs "
-    "while a dialog is displayed.";
-
 const char kOmniboxPreserveDefaultMatchAgainstAsyncUpdateName[] =
     "Omnibox Preserve Default Match Against Async Update";
 const char kOmniboxPreserveDefaultMatchAgainstAsyncUpdateDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 286fa510..7993fba 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -245,10 +245,6 @@
 extern const char kMobileGoogleSRPName[];
 extern const char kMobileGoogleSRPDescription[];
 
-// Title and description for the flag to enable non-modal JavaScript dialogs.
-extern const char kNonModalDialogsName[];
-extern const char kNonModalDialogsDescription[];
-
 // Title and description for the flag to preserve the default match when an
 // async match updates.
 extern const char kOmniboxPreserveDefaultMatchAgainstAsyncUpdateName[];
diff --git a/ios/chrome/browser/main/BUILD.gn b/ios/chrome/browser/main/BUILD.gn
index d32b7368..2d42e00 100644
--- a/ios/chrome/browser/main/BUILD.gn
+++ b/ios/chrome/browser/main/BUILD.gn
@@ -41,6 +41,7 @@
   deps = [
     "//base",
     "//components/keyed_service/ios",
+    "//ios/chrome/browser/app_launcher",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/crash_report/breadcrumbs",
     "//ios/chrome/browser/crash_report/breadcrumbs:feature_flags",
diff --git a/ios/chrome/browser/main/browser_agent_util.mm b/ios/chrome/browser/main/browser_agent_util.mm
index 7ef0585..4c1b439 100644
--- a/ios/chrome/browser/main/browser_agent_util.mm
+++ b/ios/chrome/browser/main/browser_agent_util.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/main/browser_agent_util.h"
 
 #include "base/feature_list.h"
+#import "ios/chrome/browser/app_launcher/app_launcher_browser_agent.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_browser_agent.h"
 #include "ios/chrome/browser/crash_report/breadcrumbs/features.h"
@@ -36,6 +37,7 @@
   WebUsageEnablerBrowserAgent::CreateForBrowser(browser);
   DeviceSharingBrowserAgent::CreateForBrowser(browser);
   UrlLoadingNotifierBrowserAgent::CreateForBrowser(browser);
+  AppLauncherBrowserAgent::CreateForBrowser(browser);
 
   // UrlLoadingBrowserAgent requires UrlLoadingNotifierBrowserAgent.
   UrlLoadingBrowserAgent::CreateForBrowser(browser);
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn
index 6740a642..eef34f9 100644
--- a/ios/chrome/browser/tabs/BUILD.gn
+++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -56,6 +56,7 @@
     "//components/security_state/ios",
     "//components/strings",
     "//ios/chrome/browser",
+    "//ios/chrome/browser/app_launcher",
     "//ios/chrome/browser/autofill",
     "//ios/chrome/browser/autofill:autofill_internal",
     "//ios/chrome/browser/browser_state",
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm
index 815fb6a..b08c89d 100644
--- a/ios/chrome/browser/tabs/tab_helper_util.mm
+++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -17,6 +17,7 @@
 #include "components/safe_browsing/core/features.h"
 #import "components/security_state/ios/insecure_input_tab_helper.h"
 #import "components/ukm/ios/ukm_url_recorder.h"
+#import "ios/chrome/browser/app_launcher/app_launcher_tab_helper.h"
 #import "ios/chrome/browser/autofill/autofill_tab_helper.h"
 #import "ios/chrome/browser/autofill/form_suggestion_tab_helper.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
@@ -97,6 +98,7 @@
   LoadTimingTabHelper::CreateForWebState(web_state);
   OverscrollActionsTabHelper::CreateForWebState(web_state);
   IOSTaskTabHelper::CreateForWebState(web_state);
+  AppLauncherTabHelper::CreateForWebState(web_state);
 
   if (base::FeatureList::IsEnabled(kInfobarOverlayUI)) {
     InfobarOverlayRequestInserter::CreateForWebState(web_state);
diff --git a/ios/chrome/browser/ui/app_launcher/BUILD.gn b/ios/chrome/browser/ui/app_launcher/BUILD.gn
deleted file mode 100644
index a94a988..0000000
--- a/ios/chrome/browser/ui/app_launcher/BUILD.gn
+++ /dev/null
@@ -1,58 +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.
-
-import("//build/config/ios/rules.gni")
-
-source_set("app_launcher") {
-  configs += [ "//build/config/compiler:enable_arc" ]
-  sources = [
-    "app_launcher_coordinator.h",
-    "app_launcher_coordinator.mm",
-    "app_launcher_util.h",
-    "app_launcher_util.mm",
-  ]
-  deps = [
-    "//base",
-    "//components/strings:components_strings_grit",
-    "//ios/chrome/app/strings:ios_strings_grit",
-    "//ios/chrome/browser",
-    "//ios/chrome/browser/app_launcher",
-    "//ios/chrome/browser/main:public",
-    "//ios/chrome/browser/overlays",
-    "//ios/chrome/browser/overlays/public/web_content_area",
-    "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
-    "//ios/chrome/browser/ui/dialogs:feature_flags",
-    "//ios/chrome/browser/web_state_list",
-    "//ios/public/provider/chrome/browser",
-    "//ios/public/provider/chrome/browser/mailto",
-    "//ios/web/public",
-    "//ios/web/public/navigation",
-    "//net",
-    "//ui/base",
-    "//url",
-  ]
-}
-
-source_set("unit_tests") {
-  configs += [ "//build/config/compiler:enable_arc" ]
-  testonly = true
-  sources = [ "app_launcher_coordinator_unittest.mm" ]
-  deps = [
-    ":app_launcher",
-    "//base",
-    "//base/test:test_support",
-    "//ios/chrome/app/strings:ios_strings_grit",
-    "//ios/chrome/browser/app_launcher",
-    "//ios/chrome/browser/main:test_support",
-    "//ios/chrome/browser/overlays",
-    "//ios/chrome/browser/overlays/public/web_content_area",
-    "//ios/chrome/browser/ui/dialogs:feature_flags",
-    "//ios/chrome/test:test_support",
-    "//ios/web/public/test/fakes",
-    "//testing/gtest",
-    "//third_party/ocmock",
-    "//ui/base",
-    "//url",
-  ]
-}
diff --git a/ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.h b/ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.h
deleted file mode 100644
index fc848d1..0000000
--- a/ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_APP_LAUNCHER_APP_LAUNCHER_COORDINATOR_H_
-#define IOS_CHROME_BROWSER_UI_APP_LAUNCHER_APP_LAUNCHER_COORDINATOR_H_
-
-#import <UIKit/UIKit.h>
-
-#import "ios/chrome/browser/app_launcher/app_launcher_tab_helper_delegate.h"
-#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
-
-// A coordinator that handles UI related to launching apps.
-@interface AppLauncherCoordinator
-    : ChromeCoordinator <AppLauncherTabHelperDelegate>
-
-// Unavailable, use -initWithBaseViewController:browser:.
-- (instancetype)initWithBaseViewController:(UIViewController*)viewController
-    NS_UNAVAILABLE;
-// Unavailable, use -initWithBaseViewController:browser:.
-- (instancetype)initWithBaseViewController:(UIViewController*)viewController
-                              browserState:(ChromeBrowserState*)browserState
-    NS_UNAVAILABLE;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_APP_LAUNCHER_APP_LAUNCHER_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.mm b/ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.mm
deleted file mode 100644
index 0b6f446..0000000
--- a/ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.mm
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.h"
-
-#import <UIKit/UIKit.h>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "components/strings/grit/components_strings.h"
-#import "ios/chrome/browser/app_launcher/app_launcher_tab_helper.h"
-#import "ios/chrome/browser/main/browser.h"
-#include "ios/chrome/browser/overlays/public/overlay_callback_manager.h"
-#import "ios/chrome/browser/overlays/public/overlay_request.h"
-#import "ios/chrome/browser/overlays/public/overlay_request_queue.h"
-#import "ios/chrome/browser/overlays/public/overlay_response.h"
-#import "ios/chrome/browser/overlays/public/web_content_area/app_launcher_alert_overlay.h"
-#include "ios/chrome/browser/procedural_block_types.h"
-#import "ios/chrome/browser/ui/app_launcher/app_launcher_util.h"
-#import "ios/chrome/browser/ui/dialogs/dialog_features.h"
-#import "ios/chrome/browser/web_state_list/web_state_list.h"
-#import "ios/chrome/browser/web_state_list/web_state_opener.h"
-#include "ios/chrome/grit/ios_strings.h"
-#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
-#include "ios/public/provider/chrome/browser/mailto/mailto_handler_provider.h"
-#import "ios/web/public/navigation/navigation_manager.h"
-#import "ios/web/public/web_state.h"
-#import "net/base/mac/url_conversions.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "url/gurl.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-
-// Records histogram metric on the user's response when prompted to open another
-// application. |user_accepted| should be YES if the user accepted the prompt to
-// launch another application. This call is extracted to a separate function to
-// reduce macro code expansion.
-void RecordUserAcceptedAppLaunchMetric(BOOL user_accepted) {
-  UMA_HISTOGRAM_BOOLEAN("Tab.ExternalApplicationOpened", user_accepted);
-}
-
-// Callback for the app launcher alert overlay.
-void AppLauncherOverlayCallback(ProceduralBlockWithBool app_launch_completion,
-                                OverlayResponse* response) {
-  DCHECK(app_launch_completion);
-  if (!response) {
-    app_launch_completion(NO);
-    return;
-  }
-
-  AppLauncherAlertOverlayResponseInfo* info =
-      response->GetInfo<AppLauncherAlertOverlayResponseInfo>();
-  bool allow_navigation = info ? info->allow_navigation() : false;
-  app_launch_completion(allow_navigation);
-}
-
-}  // namespace
-
-@implementation AppLauncherCoordinator
-@synthesize baseViewController = _baseViewController;
-
-#pragma mark - Private methods
-
-// Alerts the user with |message| and buttons with titles
-// |acceptActionTitle| and |rejectActionTitle|. |completionHandler| is called
-// with a BOOL indicating whether the user has tapped the accept button.
-- (void)showAlertWithMessage:(NSString*)message
-           acceptActionTitle:(NSString*)acceptActionTitle
-           rejectActionTitle:(NSString*)rejectActionTitle
-           completionHandler:(ProceduralBlockWithBool)completionHandler {
-  DCHECK(!base::FeatureList::IsEnabled(dialogs::kNonModalDialogs));
-  UIAlertController* alertController =
-      [UIAlertController alertControllerWithTitle:nil
-                                          message:message
-                                   preferredStyle:UIAlertControllerStyleAlert];
-  UIAlertAction* acceptAction =
-      [UIAlertAction actionWithTitle:acceptActionTitle
-                               style:UIAlertActionStyleDefault
-                             handler:^(UIAlertAction* action) {
-                               completionHandler(YES);
-                             }];
-  UIAlertAction* rejectAction =
-      [UIAlertAction actionWithTitle:rejectActionTitle
-                               style:UIAlertActionStyleCancel
-                             handler:^(UIAlertAction* action) {
-                               completionHandler(NO);
-                             }];
-  [alertController addAction:rejectAction];
-  [alertController addAction:acceptAction];
-
-  [self.baseViewController presentViewController:alertController
-                                        animated:YES
-                                      completion:nil];
-}
-
-// Shows an alert that the app will open in another application. If the user
-// accepts, the |URL| is launched.
-- (void)showAlertAndLaunchAppURL:(const GURL&)URL
-                        webState:(web::WebState*)webState {
-  NSString* prompt = l10n_util::GetNSString(IDS_IOS_OPEN_IN_ANOTHER_APP);
-  NSString* openLabel =
-      l10n_util::GetNSString(IDS_IOS_APP_LAUNCHER_OPEN_APP_BUTTON_LABEL);
-  NSString* cancelLabel = l10n_util::GetNSString(IDS_CANCEL);
-  NSURL* copiedURL = net::NSURLWithGURL(URL);
-  ProceduralBlockWithBool completion = ^(BOOL userAccepted) {
-    RecordUserAcceptedAppLaunchMetric(userAccepted);
-    if (userAccepted) {
-      [[UIApplication sharedApplication] openURL:copiedURL
-                                         options:@{}
-                               completionHandler:nil];
-    }
-  };
-
-  if (base::FeatureList::IsEnabled(dialogs::kNonModalDialogs)) {
-    std::unique_ptr<OverlayRequest> request =
-        OverlayRequest::CreateWithConfig<AppLauncherAlertOverlayRequestConfig>(
-            /*is_repeated_request=*/false);
-    request->GetCallbackManager()->AddCompletionCallback(
-        base::BindOnce(&AppLauncherOverlayCallback, completion));
-    [self overlayRequestQueueForWebState:webState]->AddRequest(
-        std::move(request));
-  } else {
-    [self showAlertWithMessage:prompt
-             acceptActionTitle:openLabel
-             rejectActionTitle:cancelLabel
-             completionHandler:completion];
-  }
-}
-
-// Returns the OverlayRequestQueue to use when displaying the app launcher
-// dialog when requested by |webState|.
-- (OverlayRequestQueue*)overlayRequestQueueForWebState:
-    (web::WebState*)webState {
-  web::WebState* queueWebState = webState;
-  // If an app launch navigation is occurring in a new tab, the tab will be
-  // closed immediately after the navigation fails, cancelling the app launcher
-  // dialog before it gets a chance to be shown.  When this occurs, use the
-  // OverlayRequestQueue for the tab's opener instead.
-  if (!webState->GetNavigationManager()->GetItemCount() &&
-      webState->HasOpener()) {
-    WebStateList* webStateList = self.browser->GetWebStateList();
-    int index = webStateList->GetIndexOfWebState(webState);
-    queueWebState =
-        webStateList->GetOpenerOfWebStateAt(index).opener ?: queueWebState;
-  }
-  return OverlayRequestQueue::FromWebState(queueWebState,
-                                           OverlayModality::kWebContentArea);
-}
-
-#pragma mark - AppLauncherTabHelperDelegate
-
-- (BOOL)appLauncherTabHelper:(AppLauncherTabHelper*)tabHelper
-            launchAppWithURL:(const GURL&)URL
-              linkTransition:(BOOL)linkTransition {
-  // Don't open application if chrome is not active.
-  if ([[UIApplication sharedApplication] applicationState] !=
-      UIApplicationStateActive) {
-    return NO;
-  }
-  web::WebState* webState = tabHelper->web_state();
-  if (UrlHasAppStoreScheme(URL)) {
-    [self showAlertAndLaunchAppURL:URL webState:webState];
-    return YES;
-  }
-
-  // Uses a Mailto Handler to open the appropriate app, if available.
-  if (URL.SchemeIs(url::kMailToScheme)) {
-    MailtoHandlerProvider* provider =
-        ios::GetChromeBrowserProvider()->GetMailtoHandlerProvider();
-    provider->HandleMailtoURL(net::NSURLWithGURL(URL));
-    return YES;
-  }
-
-  // For all other apps other than AppStore, show a prompt if there was no
-  // link transition.
-  if (linkTransition) {
-    [[UIApplication sharedApplication] openURL:net::NSURLWithGURL(URL)
-                                       options:@{}
-                             completionHandler:nil];
-  } else {
-    [self showAlertAndLaunchAppURL:URL webState:webState];
-  }
-  return YES;
-}
-
-- (void)appLauncherTabHelper:(AppLauncherTabHelper*)tabHelper
-    showAlertOfRepeatedLaunchesWithCompletionHandler:
-        (ProceduralBlockWithBool)completionHandler {
-  NSString* message =
-      l10n_util::GetNSString(IDS_IOS_OPEN_REPEATEDLY_ANOTHER_APP);
-  NSString* allowLaunchTitle =
-      l10n_util::GetNSString(IDS_IOS_OPEN_REPEATEDLY_ANOTHER_APP_ALLOW);
-  NSString* blockLaunchTitle =
-      l10n_util::GetNSString(IDS_IOS_OPEN_REPEATEDLY_ANOTHER_APP_BLOCK);
-  ProceduralBlockWithBool completion = ^(BOOL userAllowed) {
-    UMA_HISTOGRAM_BOOLEAN("IOS.RepeatedExternalAppPromptResponse", userAllowed);
-    completionHandler(userAllowed);
-  };
-
-  if (base::FeatureList::IsEnabled(dialogs::kNonModalDialogs)) {
-    std::unique_ptr<OverlayRequest> request =
-        OverlayRequest::CreateWithConfig<AppLauncherAlertOverlayRequestConfig>(
-            /* is_repeated_request= */ true);
-    request->GetCallbackManager()->AddCompletionCallback(
-        base::BindOnce(&AppLauncherOverlayCallback, completion));
-    OverlayRequestQueue::FromWebState(tabHelper->web_state(),
-                                      OverlayModality::kWebContentArea)
-        ->AddRequest(std::move(request));
-  } else {
-    [self showAlertWithMessage:message
-             acceptActionTitle:allowLaunchTitle
-             rejectActionTitle:blockLaunchTitle
-             completionHandler:completion];
-  }
-}
-
-@end
diff --git a/ios/chrome/browser/ui/app_launcher/app_launcher_coordinator_unittest.mm b/ios/chrome/browser/ui/app_launcher/app_launcher_coordinator_unittest.mm
deleted file mode 100644
index 38f9939..0000000
--- a/ios/chrome/browser/ui/app_launcher/app_launcher_coordinator_unittest.mm
+++ /dev/null
@@ -1,124 +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.
-
-#import "ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.h"
-
-#import <UIKit/UIKit.h>
-
-#include "base/mac/foundation_util.h"
-#include "base/test/task_environment.h"
-#import "ios/chrome/browser/app_launcher/app_launcher_tab_helper.h"
-#include "ios/chrome/browser/main/test_browser.h"
-#include "ios/chrome/browser/overlays/public/overlay_request.h"
-#import "ios/chrome/browser/overlays/public/overlay_request_queue.h"
-#import "ios/chrome/browser/overlays/public/web_content_area/app_launcher_alert_overlay.h"
-#import "ios/chrome/browser/ui/dialogs/dialog_features.h"
-#include "ios/chrome/grit/ios_strings.h"
-#import "ios/chrome/test/scoped_key_window.h"
-#import "ios/web/public/test/fakes/test_navigation_manager.h"
-#import "ios/web/public/test/fakes/test_web_state.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-#import "third_party/ocmock/OCMock/OCMock.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "url/gurl.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-// Test fixture for AppLauncherCoordinator class.
-class AppLauncherCoordinatorTest : public PlatformTest {
- protected:
-  AppLauncherCoordinatorTest() {
-    base_view_controller_ = [[UIViewController alloc] init];
-    [scoped_key_window_.Get() setRootViewController:base_view_controller_];
-    browser_ = std::make_unique<TestBrowser>();
-    coordinator_ = [[AppLauncherCoordinator alloc]
-        initWithBaseViewController:base_view_controller_
-                           browser:browser_.get()];
-    application_ = OCMClassMock([UIApplication class]);
-    OCMStub([application_ sharedApplication]).andReturn(application_);
-    AppLauncherTabHelper::CreateForWebState(&web_state_, nil, nil);
-    std::unique_ptr<web::TestNavigationManager> navigation_manager =
-        std::make_unique<web::TestNavigationManager>();
-    navigation_manager->AddItem(GURL("http://www.chromium.org"),
-                                ui::PAGE_TRANSITION_LINK);
-    web_state_.SetNavigationManager(std::move(navigation_manager));
-  }
-  ~AppLauncherCoordinatorTest() override {
-    [application_ stopMocking];
-    OverlayRequestQueue::FromWebState(&web_state_,
-                                      OverlayModality::kWebContentArea)
-        ->CancelAllRequests();
-  }
-
-  AppLauncherTabHelper* tab_helper() {
-    return AppLauncherTabHelper::FromWebState(&web_state_);
-  }
-
-  bool IsShowingDialog(bool is_repeated_request) {
-    if (base::FeatureList::IsEnabled(dialogs::kNonModalDialogs)) {
-      OverlayRequest* request =
-          OverlayRequestQueue::FromWebState(&web_state_,
-                                            OverlayModality::kWebContentArea)
-              ->front_request();
-      if (!request)
-        return false;
-      AppLauncherAlertOverlayRequestConfig* config =
-          request->GetConfig<AppLauncherAlertOverlayRequestConfig>();
-      return config && config->is_repeated_request() == is_repeated_request;
-    } else {
-      UIAlertController* alert_controller =
-          base::mac::ObjCCastStrict<UIAlertController>(
-              base_view_controller_.presentedViewController);
-      NSString* message =
-          is_repeated_request
-              ? l10n_util::GetNSString(IDS_IOS_OPEN_REPEATEDLY_ANOTHER_APP)
-              : l10n_util::GetNSString(IDS_IOS_OPEN_IN_ANOTHER_APP);
-      return alert_controller.message == message;
-    }
-  }
-
-  base::test::TaskEnvironment task_environment_;
-
-  web::TestWebState web_state_;
-  UIViewController* base_view_controller_ = nil;
-  ScopedKeyWindow scoped_key_window_;
-  std::unique_ptr<Browser> browser_;
-  AppLauncherCoordinator* coordinator_ = nil;
-  id application_ = nil;
-};
-
-
-// Tests that an itunes URL shows an alert.
-TEST_F(AppLauncherCoordinatorTest, ItmsUrlShowsAlert) {
-  BOOL app_exists = [coordinator_ appLauncherTabHelper:tab_helper()
-                                      launchAppWithURL:GURL("itms://1234")
-                                        linkTransition:NO];
-  EXPECT_TRUE(app_exists);
-  EXPECT_TRUE(IsShowingDialog(/*is_repeated_request=*/false));
-}
-
-// Tests that in the new AppLauncher, an app URL attempts to launch the
-// application.
-TEST_F(AppLauncherCoordinatorTest, AppUrlLaunchesApp) {
-  OCMExpect([application_ openURL:[NSURL URLWithString:@"some-app://1234"]
-                          options:@{}
-                completionHandler:nil]);
-  [coordinator_ appLauncherTabHelper:tab_helper()
-                    launchAppWithURL:GURL("some-app://1234")
-                      linkTransition:YES];
-  [application_ verify];
-}
-
-// Tests that in the new AppLauncher, an app URL shows a prompt if there was no
-// link transition.
-TEST_F(AppLauncherCoordinatorTest, AppUrlShowsPrompt) {
-  [coordinator_ appLauncherTabHelper:tab_helper()
-                    launchAppWithURL:GURL("some-app://1234")
-                      linkTransition:NO];
-  EXPECT_TRUE(IsShowingDialog(/*is_repeated_request=*/false));
-}
diff --git a/ios/chrome/browser/ui/browser_container/BUILD.gn b/ios/chrome/browser/ui/browser_container/BUILD.gn
index 1b2f1db..140eb35 100644
--- a/ios/chrome/browser/ui/browser_container/BUILD.gn
+++ b/ios/chrome/browser/ui/browser_container/BUILD.gn
@@ -30,7 +30,6 @@
 
   deps = [
     "//base",
-    "//ios/chrome/browser/ui/dialogs:feature_flags",
     "//ios/chrome/browser/ui/util",
   ]
 }
diff --git a/ios/chrome/browser/ui/browser_container/browser_container_view_controller.mm b/ios/chrome/browser/ui/browser_container/browser_container_view_controller.mm
index 94802bd3..01635ef 100644
--- a/ios/chrome/browser/ui/browser_container/browser_container_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_container/browser_container_view_controller.mm
@@ -5,7 +5,6 @@
 #import "ios/chrome/browser/ui/browser_container/browser_container_view_controller.h"
 
 #include "base/logging.h"
-#import "ios/chrome/browser/ui/dialogs/dialog_features.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -19,9 +18,6 @@
 
 - (void)viewDidLoad {
   [super viewDidLoad];
-
-  self.definesPresentationContext =
-      base::FeatureList::IsEnabled(dialogs::kNonModalDialogs);
   self.view.autoresizingMask =
       UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
 }
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn
index 27ef560..c2dec64 100644
--- a/ios/chrome/browser/ui/browser_view/BUILD.gn
+++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -76,7 +76,6 @@
     "//ios/chrome/browser/ui/activity_services:coordinator",
     "//ios/chrome/browser/ui/activity_services/requirements",
     "//ios/chrome/browser/ui/alert_coordinator",
-    "//ios/chrome/browser/ui/app_launcher",
     "//ios/chrome/browser/ui/authentication",
     "//ios/chrome/browser/ui/autofill:autofill",
     "//ios/chrome/browser/ui/autofill/form_input_accessory",
@@ -94,7 +93,6 @@
     "//ios/chrome/browser/ui/context_menu",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/dialogs:dialogs_internal",
-    "//ios/chrome/browser/ui/dialogs:feature_flags",
     "//ios/chrome/browser/ui/download",
     "//ios/chrome/browser/ui/download:features",
     "//ios/chrome/browser/ui/elements:elements_internal",
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
index 545cdd7..9c7457d 100644
--- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -22,7 +22,6 @@
 #import "ios/chrome/browser/store_kit/store_kit_tab_helper.h"
 #import "ios/chrome/browser/tabs/tab_title_util.h"
 #import "ios/chrome/browser/ui/alert_coordinator/repost_form_coordinator.h"
-#import "ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.h"
 #import "ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_coordinator.h"
 #import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_all_password_coordinator.h"
 #import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_injection_handler.h"
@@ -107,9 +106,6 @@
 // Child Coordinators, listed in alphabetical order.
 // =================================================
 
-// Coordinator for UI related to launching external apps.
-@property(nonatomic, strong) AppLauncherCoordinator* appLauncherCoordinator;
-
 // Presents a QLPreviewController in order to display USDZ format 3D models.
 @property(nonatomic, strong) ARQuickLookCoordinator* ARQuickLookCoordinator;
 
@@ -334,11 +330,6 @@
   // coordinators.
   DCHECK(self.dispatcher);
 
-  self.appLauncherCoordinator = [[AppLauncherCoordinator alloc]
-      initWithBaseViewController:self.viewController
-                         browser:self.browser];
-  [self.appLauncherCoordinator start];
-
   self.ARQuickLookCoordinator = [[ARQuickLookCoordinator alloc]
       initWithBaseViewController:self.viewController
                          browser:self.browser];
@@ -424,9 +415,6 @@
   [self.allPasswordCoordinator stop];
   self.allPasswordCoordinator = nil;
 
-  [self.appLauncherCoordinator stop];
-  self.appLauncherCoordinator = nil;
-
   [self.ARQuickLookCoordinator stop];
   self.ARQuickLookCoordinator = nil;
 
@@ -956,10 +944,6 @@
 
 // Install delegates for |webState|.
 - (void)installDelegatesForWebState:(web::WebState*)webState {
-  AppLauncherTabHelper::CreateForWebState(
-      webState, [[AppLauncherAbuseDetector alloc] init],
-      self.appLauncherCoordinator);
-
   if (AutofillTabHelper::FromWebState(webState)) {
     AutofillTabHelper::FromWebState(webState)->SetBaseViewController(
         self.viewController);
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index 3a06d1c..34e3aa29 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -85,9 +85,6 @@
 #import "ios/chrome/browser/ui/commands/text_zoom_commands.h"
 #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h"
 #import "ios/chrome/browser/ui/context_menu/context_menu_coordinator.h"
-#import "ios/chrome/browser/ui/dialogs/dialog_features.h"
-#import "ios/chrome/browser/ui/dialogs/dialog_presenter.h"
-#import "ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.h"
 #import "ios/chrome/browser/ui/download/download_manager_coordinator.h"
 #import "ios/chrome/browser/ui/elements/activity_overlay_coordinator.h"
 #import "ios/chrome/browser/ui/first_run/welcome_to_chrome_view_controller.h"
@@ -331,7 +328,6 @@
                                      CaptivePortalDetectorTabHelperDelegate,
                                      CRWWebStateDelegate,
                                      CRWWebStateObserver,
-                                     DialogPresenterDelegate,
                                      FullscreenUIElement,
                                      InfobarPositioner,
                                      KeyCommandsPlumbing,
@@ -371,9 +367,6 @@
   // Handles displaying the context menu for all form factors.
   ContextMenuCoordinator* _contextMenuCoordinator;
 
-  // Backing object for property of the same name.
-  DialogPresenter* _dialogPresenter;
-
   // Handles presentation of JavaScript dialogs.
   std::unique_ptr<web::JavaScriptDialogPresenter> _javaScriptDialogPresenter;
 
@@ -479,8 +472,6 @@
 @property(nonatomic, weak) CommandDispatcher* commandDispatcher;
 // The browser's side swipe controller.  Lazily instantiated on the first call.
 @property(nonatomic, strong, readonly) SideSwipeController* sideSwipeController;
-// The dialog presenter for this BVC's tab model.
-@property(nonatomic, strong, readonly) DialogPresenter* dialogPresenter;
 // The object that manages keyboard commands on behalf of the BVC.
 @property(nonatomic, strong, readonly) KeyCommandsProvider* keyCommandsProvider;
 // Whether the controller's view is currently available.
@@ -638,9 +629,6 @@
 // Starts or stops broadcasting the toolbar UI and main content UI depending on
 // whether the BVC is visible and active.
 - (void)updateBroadcastState;
-// Updates |dialogPresenter|'s |active| property to account for the BVC's
-// |active|, |visible|, and |inNewTabAnimation| properties.
-- (void)updateDialogPresenterActiveState;
 // Dismisses popups and modal dialogs that are displayed above the BVC upon size
 // changes (e.g. rotation, resizing,…) or when the accessibility escape gesture
 // is performed.
@@ -741,12 +729,6 @@
           [[VerticalAnimationContainer alloc] init];
     }
 
-    if (!base::FeatureList::IsEnabled(dialogs::kNonModalDialogs)) {
-      _dialogPresenter = [[DialogPresenter alloc] initWithDelegate:self
-                                          presentingViewController:self];
-      _javaScriptDialogPresenter =
-          std::make_unique<JavaScriptDialogPresenterImpl>(_dialogPresenter);
-    }
     _webStateDelegate.reset(new web::WebStateDelegateBridge(self));
     _inNewTabAnimation = NO;
 
@@ -865,10 +847,6 @@
   return _sideSwipeController;
 }
 
-- (DialogPresenter*)dialogPresenter {
-  return _dialogPresenter;
-}
-
 - (KeyCommandsProvider*)keyCommandsProvider {
   if (!_keyCommandsProvider) {
     _keyCommandsProvider = [_dependencyFactory newKeyCommandsProvider];
@@ -904,7 +882,6 @@
     return;
   _viewVisible = viewVisible;
   self.visible = viewVisible;
-  [self updateDialogPresenterActiveState];
   [self updateBroadcastState];
 }
 
@@ -976,7 +953,6 @@
   if (_inNewTabAnimation == inNewTabAnimation)
     return;
   _inNewTabAnimation = inNewTabAnimation;
-  [self updateDialogPresenterActiveState];
   [self updateBroadcastState];
 }
 
@@ -1063,10 +1039,7 @@
 - (void)setPrimary:(BOOL)primary {
   [self.tabModel setPrimary:primary];
   if (primary) {
-    [self updateDialogPresenterActiveState];
     [self updateBroadcastState];
-  } else {
-    self.dialogPresenter.active = false;
   }
 }
 
@@ -1199,7 +1172,6 @@
   }
 
   self.webUsageEnabled = active;
-  [self updateDialogPresenterActiveState];
   [self updateBroadcastState];
 
   // Stop the NTP on web usage toggle. This happens when clearing browser
@@ -1222,8 +1194,6 @@
     }
     if (self.currentWebState)
       [self displayWebState:self.currentWebState];
-  } else {
-    [_dialogPresenter cancelAllDialogs];
   }
 
   [self setNeedsStatusBarAppearanceUpdate];
@@ -1237,7 +1207,6 @@
   if (dismissOmnibox) {
     [self.omniboxHandler cancelOmniboxEdit];
   }
-  [_dialogPresenter cancelAllDialogs];
   [self.helpHandler hideAllHelpBubbles];
   if (_voiceSearchController)
     _voiceSearchController->DismissMicPermissionsHelp();
@@ -1499,7 +1468,6 @@
 - (void)viewDidAppear:(BOOL)animated {
   [super viewDidAppear:animated];
   self.viewVisible = YES;
-  [self updateDialogPresenterActiveState];
   [self updateBroadcastState];
   [_toolbarUIUpdater updateState];
   [self.infobarContainerCoordinator baseViewDidAppear];
@@ -1542,7 +1510,6 @@
 
 - (void)viewWillDisappear:(BOOL)animated {
   self.viewVisible = NO;
-  [self updateDialogPresenterActiveState];
   [self updateBroadcastState];
   web::WebState* activeWebState =
       self.browser ? self.browser->GetWebStateList()->GetActiveWebState()
@@ -1709,7 +1676,6 @@
                               strongSelf.dismissingModal = NO;
                               if (completion)
                                 completion();
-                              [strongSelf.dialogPresenter tryToPresent];
                             }];
 }
 
@@ -2447,11 +2413,6 @@
   self.broadcasting = self.active && self.viewVisible;
 }
 
-- (void)updateDialogPresenterActiveState {
-  self.dialogPresenter.active =
-      self.active && self.viewVisible && !self.inNewTabAnimation;
-}
-
 - (void)dismissPopups {
   // The dispatcher may not be fully connected during shutdown, so selectors may
   // be unrecognized.
@@ -3243,12 +3204,8 @@
 
 - (web::JavaScriptDialogPresenter*)javaScriptDialogPresenterForWebState:
     (web::WebState*)webState {
-  if (base::FeatureList::IsEnabled(dialogs::kNonModalDialogs)) {
-    return WebStateDelegateTabHelper::FromWebState(webState)
-        ->GetJavaScriptDialogPresenter(webState);
-  }
-  DCHECK(_javaScriptDialogPresenter.get());
-  return _javaScriptDialogPresenter.get();
+  return WebStateDelegateTabHelper::FromWebState(webState)
+      ->GetJavaScriptDialogPresenter(webState);
 }
 
 - (void)webState:(web::WebState*)webState
@@ -3257,19 +3214,12 @@
                        completionHandler:(void (^)(NSString* username,
                                                    NSString* password))handler {
   DCHECK(handler);
-  if (base::FeatureList::IsEnabled(dialogs::kNonModalDialogs)) {
-    web::WebStateDelegate::AuthCallback callback =
-        base::BindRepeating(^(NSString* user, NSString* password) {
-          handler(user, password);
-        });
-    WebStateDelegateTabHelper::FromWebState(webState)->OnAuthRequired(
-        webState, protectionSpace, proposedCredential, callback);
-  } else {
-    [self.dialogPresenter runAuthDialogForProtectionSpace:protectionSpace
-                                       proposedCredential:proposedCredential
-                                                 webState:webState
-                                        completionHandler:handler];
-  }
+  web::WebStateDelegate::AuthCallback callback =
+      base::BindRepeating(^(NSString* user, NSString* password) {
+        handler(user, password);
+      });
+  WebStateDelegateTabHelper::FromWebState(webState)->OnAuthRequired(
+      webState, protectionSpace, proposedCredential, callback);
 }
 
 - (BOOL)webState:(web::WebState*)webState
@@ -3544,28 +3494,6 @@
   return self.fullscreenController;
 }
 
-#pragma mark - DialogPresenterDelegate methods
-
-- (void)dialogPresenter:(DialogPresenter*)presenter
-    willShowDialogForWebState:(web::WebState*)webState {
-  WebStateList* webStateList = self.browser->GetWebStateList();
-  int indexOfWebState = webStateList->GetIndexOfWebState(webState);
-  if (indexOfWebState != WebStateList::kInvalidIndex) {
-    webStateList->ActivateWebStateAt(indexOfWebState);
-    DCHECK([webState->GetView() isDescendantOfView:self.contentArea]);
-  }
-}
-
-- (BOOL)shouldDialogPresenterPresentDialog:(DialogPresenter*)presenter {
-  if (self.presentedViewController)
-    return NO;
-  for (UIViewController* childViewController in self.childViewControllers) {
-    if (childViewController.presentedViewController)
-      return NO;
-  }
-  return YES;
-}
-
 #pragma mark - ToolbarHeightProviderForFullscreen
 
 - (CGFloat)collapsedTopToolbarHeight {
@@ -4194,9 +4122,6 @@
 
   [self uninstallDelegatesForWebState:webState];
 
-  // Cancel dialogs for |webState|.
-  [self.dialogPresenter cancelDialogForWebState:webState];
-
   // Ignore changes while the tab grid is visible (or while suspended).
   // The display will be refreshed when this view becomes active again.
   if (!self.visible || !self.webUsageEnabled)
@@ -4586,7 +4511,6 @@
 }
 
 - (void)activityServiceDidEndPresenting {
-  [self.dialogPresenter tryToPresent];
 }
 
 - (void)showActivityServiceErrorAlertWithStringTitle:(NSString*)title
diff --git a/ios/chrome/browser/ui/dialogs/BUILD.gn b/ios/chrome/browser/ui/dialogs/BUILD.gn
index 01f14cb6..e343942 100644
--- a/ios/chrome/browser/ui/dialogs/BUILD.gn
+++ b/ios/chrome/browser/ui/dialogs/BUILD.gn
@@ -16,20 +16,6 @@
   configs += [ "//build/config/compiler:enable_arc" ]
 }
 
-source_set("feature_flags") {
-  sources = [
-    "dialog_features.h",
-    "dialog_features.mm",
-  ]
-
-  configs += [ "//build/config/compiler:enable_arc" ]
-
-  deps = [
-    "//base",
-    "//components/flags_ui",
-  ]
-}
-
 source_set("unit_tests") {
   testonly = true
 
@@ -56,12 +42,8 @@
 source_set("dialogs_internal") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
-    "dialog_presenter.h",
-    "dialog_presenter.mm",
     "java_script_dialog_metrics.cc",
     "java_script_dialog_metrics.h",
-    "java_script_dialog_presenter_impl.h",
-    "java_script_dialog_presenter_impl.mm",
     "nsurl_protection_space_util.h",
     "nsurl_protection_space_util.mm",
     "overlay_java_script_dialog_presenter.h",
@@ -101,8 +83,6 @@
   testonly = true
   sources = [
     "completion_block_util_unittest.mm",
-    "dialog_presenter_unittest.mm",
-    "java_script_dialog_presenter_impl_unittest.mm",
     "nsurl_protection_space_util_unittest.mm",
     "overlay_java_script_dialog_presenter_unittest.mm",
   ]
@@ -130,7 +110,6 @@
   sources = [ "javascript_dialog_egtest.mm" ]
   deps = [
     ":constants",
-    ":feature_flags",
     "//base",
     "//base/test:test_support",
     "//components/strings",
@@ -167,7 +146,6 @@
   sources = [ "javascript_dialog_egtest.mm" ]
   deps = [
     ":constants",
-    ":feature_flags",
     "//base",
     "//base/test:test_support",
     "//components/strings",
diff --git a/ios/chrome/browser/ui/dialogs/dialog_features.h b/ios/chrome/browser/ui/dialogs/dialog_features.h
deleted file mode 100644
index 9f7a79a..0000000
--- a/ios/chrome/browser/ui/dialogs/dialog_features.h
+++ /dev/null
@@ -1,17 +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 IOS_CHROME_BROWSER_UI_DIALOGS_DIALOG_FEATURES_H_
-#define IOS_CHROME_BROWSER_UI_DIALOGS_DIALOG_FEATURES_H_
-
-#include "base/feature_list.h"
-
-namespace dialogs {
-
-// Feature flag to use non-modal UI for JavaScript dialogs.
-extern const base::Feature kNonModalDialogs;
-
-}  // namespace dialogs
-
-#endif  // IOS_CHROME_BROWSER_UI_DIALOGS_DIALOG_FEATURES_H_
diff --git a/ios/chrome/browser/ui/dialogs/dialog_features.mm b/ios/chrome/browser/ui/dialogs/dialog_features.mm
deleted file mode 100644
index 8cc9ccb..0000000
--- a/ios/chrome/browser/ui/dialogs/dialog_features.mm
+++ /dev/null
@@ -1,16 +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.
-
-#import "ios/chrome/browser/ui/dialogs/dialog_features.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace dialogs {
-
-const base::Feature kNonModalDialogs{"kNonModalDialogs",
-                                     base::FEATURE_ENABLED_BY_DEFAULT};
-
-}  // namespace dialogs
diff --git a/ios/chrome/browser/ui/dialogs/dialog_presenter.h b/ios/chrome/browser/ui/dialogs/dialog_presenter.h
deleted file mode 100644
index 8046e156..0000000
--- a/ios/chrome/browser/ui/dialogs/dialog_presenter.h
+++ /dev/null
@@ -1,101 +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.
-
-#ifndef IOS_CHROME_BROWSER_UI_DIALOGS_DIALOG_PRESENTER_H_
-#define IOS_CHROME_BROWSER_UI_DIALOGS_DIALOG_PRESENTER_H_
-
-#import <UIKit/UIKit.h>
-
-#import "base/ios/block_types.h"
-
-@protocol DialogPresenterDelegate;
-class GURL;
-@class AlertCoordinator;
-
-namespace web {
-class WebState;
-}
-
-// Handles the queued display of modal dialogs.
-@interface DialogPresenter : NSObject
-
-// Whether the DialogPresenter should attempt to show dialogs.  When |active| is
-// NO, dialogs will be queued and displayed when the DialogPresenter is
-// activated.
-@property(nonatomic, assign, getter=isActive) BOOL active;
-
-// Dialogs will be presented from |viewController|.
-- (instancetype)initWithDelegate:(id<DialogPresenterDelegate>)delegate
-        presentingViewController:(UIViewController*)viewController
-    NS_DESIGNATED_INITIALIZER;
-- (instancetype)init NS_UNAVAILABLE;
-
-// Methods to show JavaScriptDialogs of each JavaScriptAlertType.  If a dialog
-// is already being presented, these functions will enqueue a new dialog to be
-// shown when the visible dialog is dismissed.  |context| will be retained until
-// its associated dialog is dismissed or |-cancelDialogForContext:| is called.
-- (void)runJavaScriptAlertPanelWithMessage:(NSString*)message
-                                requestURL:(const GURL&)requestURL
-                                  webState:(web::WebState*)webState
-                         completionHandler:(void (^)(void))completionHandler;
-- (void)runJavaScriptConfirmPanelWithMessage:(NSString*)message
-                                  requestURL:(const GURL&)requestURL
-                                    webState:(web::WebState*)webState
-                           completionHandler:
-                               (void (^)(BOOL isConfirmed))completionHandler;
-- (void)runJavaScriptTextInputPanelWithPrompt:(NSString*)message
-                                  defaultText:(NSString*)defaultText
-                                   requestURL:(const GURL&)requestURL
-                                     webState:(web::WebState*)webState
-                            completionHandler:
-                                (void (^)(NSString* input))completionHandler;
-
-// Displays an HTTP authentication dialog, which has 2 text fields
-// (username and password), Login and Cancel button. If Login was tapped,
-// |completionHandler| is called with valid strings which represent username
-// and password inputs. If cancel is tapped then |completionHandler| is
-// called with nil |user| and nil |password|. Username will be pre-populated
-// from provided |credential|.
-- (void)runAuthDialogForProtectionSpace:(NSURLProtectionSpace*)protectionSpace
-                     proposedCredential:(NSURLCredential*)credential
-                               webState:(web::WebState*)webState
-                      completionHandler:
-                          (void (^)(NSString* user, NSString* password))handler;
-
-// Cancels the display of the dialog associated with |context|.
-- (void)cancelDialogForWebState:(web::WebState*)webState;
-
-// Dismisses the currently presented dialog and cancels all queued dialogs.
-- (void)cancelAllDialogs;
-
-// Tries to present an alert if needed and possible. Called by the view
-// controller which will present the alert to notify that it has dismissed a
-// view controller.
-- (void)tryToPresent;
-
-@end
-
-@interface DialogPresenter (ExposedForTesting)
-// The dialog currently being shown.
-@property(nonatomic, readonly) AlertCoordinator* presentedDialogCoordinator;
-
-// Called when |coordinator| is stopped.
-- (void)dialogCoordinatorWasStopped:(AlertCoordinator*)coordinator;
-
-@end
-
-// Delegate protocol for DialogPresenter.
-@protocol DialogPresenterDelegate<NSObject>
-
-// Called by |presenter| before showing the queued modal dialog associated with
-// |context|.
-- (void)dialogPresenter:(DialogPresenter*)presenter
-    willShowDialogForWebState:(web::WebState*)webState;
-
-// Whether |presenter| should present a dialog.
-- (BOOL)shouldDialogPresenterPresentDialog:(DialogPresenter*)presenter;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_DIALOGS_DIALOG_PRESENTER_H_
diff --git a/ios/chrome/browser/ui/dialogs/dialog_presenter.mm b/ios/chrome/browser/ui/dialogs/dialog_presenter.mm
deleted file mode 100644
index 719b17b8..0000000
--- a/ios/chrome/browser/ui/dialogs/dialog_presenter.mm
+++ /dev/null
@@ -1,577 +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.
-
-#import "ios/chrome/browser/ui/dialogs/dialog_presenter.h"
-
-#include <map>
-
-#include "base/containers/circular_deque.h"
-#import "base/ios/block_types.h"
-#include "base/logging.h"
-#include "components/strings/grit/components_strings.h"
-#include "components/url_formatter/elide_url.h"
-#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
-#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
-#import "ios/chrome/browser/ui/alert_coordinator/input_alert_coordinator.h"
-#import "ios/chrome/browser/ui/dialogs/completion_block_util.h"
-#import "ios/chrome/browser/ui/dialogs/dialog_constants.h"
-#import "ios/chrome/browser/ui/dialogs/java_script_dialog_blocking_state.h"
-#import "ios/chrome/browser/ui/dialogs/nsurl_protection_space_util.h"
-#include "ios/chrome/browser/ui/util/ui_util.h"
-#include "ios/chrome/grit/ios_strings.h"
-#import "ios/web/public/navigation/navigation_context.h"
-#import "ios/web/public/web_state.h"
-#import "ios/web/public/web_state_observer_bridge.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "url/gurl.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-using completion_block_util::AlertCallback;
-using completion_block_util::ConfirmCallback;
-using completion_block_util::PromptCallback;
-using completion_block_util::HTTPAuthCallack;
-using completion_block_util::GetSafeJavaScriptAlertCompletion;
-using completion_block_util::GetSafeJavaScriptConfirmationCompletion;
-using completion_block_util::GetSafeJavaScriptPromptCompletion;
-using completion_block_util::GetSafeHTTPAuthCompletion;
-
-@interface DialogPresenter () <CRWWebStateObserver> {
-  // Queue of WebStates which correspond to the keys in
-  // |_dialogCoordinatorsForWebStates|.
-  base::circular_deque<web::WebState*> _queuedWebStates;
-  // A map associating queued webStates with their coordinators.
-  std::map<web::WebState*, AlertCoordinator*> _dialogCoordinatorsForWebStates;
-  // The WebStateObserver listening for navigation events from the queued
-  // WebStates.
-  std::unique_ptr<web::WebStateObserver> _webStateObserver;
-}
-
-// The delegate passed on initialization.
-@property(weak, nonatomic, readonly) id<DialogPresenterDelegate> delegate;
-
-// The presenting view controller passed on initialization.
-@property(weak, nonatomic, readonly) UIViewController* viewController;
-
-// Whether a modal dialog is currently being shown.
-@property(nonatomic, readonly, getter=isShowingDialog) BOOL showingDialog;
-
-// The webState for |presentedDialog|.
-@property(nonatomic) web::WebState* presentedDialogWebState;
-
-// The dialog that's currently being shown, if any.
-@property(nonatomic, strong) AlertCoordinator* presentedDialogCoordinator;
-
-// The JavaScript dialog blocking confirmation action sheet being shown, if any.
-@property(nonatomic, strong) AlertCoordinator* blockingConfirmationCoordinator;
-
-// Adds |context| and |coordinator| to the queue.  If a dialog is not already
-// being shown, |coordinator| will be presented.  Otherwise, |coordinator| will
-// be displayed once the previously shown dialog is dismissed.
-- (void)addDialogCoordinator:(AlertCoordinator*)coordinator
-                 forWebState:(web::WebState*)webState;
-
-// Shows the dialog associated with the next context in |contextQueue|.
-- (void)showNextDialog;
-
-// Called when |coordinator| is stopped.
-- (void)dialogCoordinatorWasStopped:(AlertCoordinator*)coordinator;
-
-// Adds buttons to |alertCoordinator|.  A confirmation button with |label| as
-// the text will be added for |confirmAction|, and a cancel button will be added
-// for |cancelAction|.
-- (void)setUpAlertCoordinator:(AlertCoordinator*)alertCoordinator
-                confirmAction:(ProceduralBlock)confirmAction
-                 cancelAction:(ProceduralBlock)cancelAction
-                      OKLabel:(NSString*)label;
-
-// Sets up the JavaScript dialog blocking option for |alertCoordinator|.
-// Overrides |alertCoordinator|'s |startAction| to call
-// JavaScriptDialogWasShown(). Depending on the value of
-// ShouldShowDialogBlockingOption() for |webState|, optionally adds a button to
-// |alertCoordinator| allowing for the blocking of future dialogs.  In addition
-// to blocking dialogs for the WebState, the added button will call
-// |alertCoordinator|'s |cancelAction|.
-- (void)setUpBlockingOptionForCoordinator:(AlertCoordinator*)alertCoordinator
-                                 webState:(web::WebState*)webState;
-
-// The block to use for the JavaScript dialog blocking option for |coordinator|.
-- (ProceduralBlock)blockingActionForCoordinator:(AlertCoordinator*)coordinator;
-
-// Creates a title for the alert based on the URL (|pageURL|), and its
-// relationship to the |mainFrameURL| (typically these are identical except for
-// when posting alerts from an embedded iframe).
-+ (NSString*)localizedTitleForJavaScriptAlertFromPage:(const GURL&)pageURL
-                                         mainFrameURL:(const GURL&)mainFrameURL;
-
-@end
-
-@implementation DialogPresenter
-
-@synthesize active = _active;
-@synthesize delegate = _delegate;
-@synthesize viewController = _viewController;
-@synthesize presentedDialogCoordinator = _presentedDialogCoordinator;
-@synthesize blockingConfirmationCoordinator = _blockingConfirmationCoordinator;
-@synthesize presentedDialogWebState = _presentedDialogWebState;
-
-- (instancetype)initWithDelegate:(id<DialogPresenterDelegate>)delegate
-        presentingViewController:(UIViewController*)viewController {
-  if ((self = [super init])) {
-    DCHECK(delegate);
-    DCHECK(viewController);
-    _delegate = delegate;
-    _viewController = viewController;
-    _webStateObserver = std::make_unique<web::WebStateObserverBridge>(self);
-  }
-  return self;
-}
-
-#pragma mark - Accessors
-
-- (void)setActive:(BOOL)active {
-  if (_active != active) {
-    _active = active;
-    [self tryToPresent];
-  }
-}
-
-- (BOOL)isShowingDialog {
-  DCHECK_EQ(self.presentedDialogWebState != nullptr,
-            self.presentedDialogCoordinator != nil);
-  return self.presentedDialogCoordinator != nil;
-}
-
-#pragma mark - Public
-
-- (void)runJavaScriptAlertPanelWithMessage:(NSString*)message
-                                requestURL:(const GURL&)requestURL
-                                  webState:(web::WebState*)webState
-                         completionHandler:(void (^)(void))completionHandler {
-  AlertCallback safeCallback =
-      GetSafeJavaScriptAlertCompletion(completionHandler);
-  NSString* title = [DialogPresenter
-      localizedTitleForJavaScriptAlertFromPage:requestURL
-                                  mainFrameURL:webState->GetLastCommittedURL()];
-  AlertCoordinator* alertCoordinator =
-      [[AlertCoordinator alloc] initWithBaseViewController:self.viewController
-                                                     title:title
-                                                   message:message];
-
-  // Handler.
-  __weak DialogPresenter* weakSelf = self;
-  __weak AlertCoordinator* weakCoordinator = alertCoordinator;
-  ProceduralBlock OKHandler = ^{
-    if (safeCallback)
-      safeCallback();
-    [weakSelf dialogCoordinatorWasStopped:weakCoordinator];
-  };
-
-  // Add button.
-  [alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_OK)
-                              action:OKHandler
-                               style:UIAlertActionStyleDefault];
-
-  // Add cancel handler.
-  alertCoordinator.cancelAction = safeCallback;
-  alertCoordinator.noInteractionAction = safeCallback;
-
-  // Blocking option setup.
-  [self setUpBlockingOptionForCoordinator:alertCoordinator webState:webState];
-
-  [self addDialogCoordinator:alertCoordinator forWebState:webState];
-}
-
-- (void)runJavaScriptConfirmPanelWithMessage:(NSString*)message
-                                  requestURL:(const GURL&)requestURL
-                                    webState:(web::WebState*)webState
-                           completionHandler:
-                               (void (^)(BOOL isConfirmed))completionHandler {
-  ConfirmCallback safeCallback =
-      GetSafeJavaScriptConfirmationCompletion(completionHandler);
-  NSString* title = [DialogPresenter
-      localizedTitleForJavaScriptAlertFromPage:requestURL
-                                  mainFrameURL:webState->GetLastCommittedURL()];
-  AlertCoordinator* alertCoordinator =
-      [[AlertCoordinator alloc] initWithBaseViewController:self.viewController
-                                                     title:title
-                                                   message:message];
-
-  // Actions.
-  ProceduralBlock confirmAction = ^{
-    if (safeCallback)
-      safeCallback(YES);
-  };
-
-  ProceduralBlock cancelAction = ^{
-    if (safeCallback)
-      safeCallback(NO);
-  };
-
-  // Coordinator Setup.
-  NSString* OKLabel = l10n_util::GetNSString(IDS_OK);
-  [self setUpAlertCoordinator:alertCoordinator
-                confirmAction:confirmAction
-                 cancelAction:cancelAction
-                      OKLabel:OKLabel];
-
-  // Blocking option setup.
-  [self setUpBlockingOptionForCoordinator:alertCoordinator webState:webState];
-
-  [self addDialogCoordinator:alertCoordinator forWebState:webState];
-}
-
-- (void)runJavaScriptTextInputPanelWithPrompt:(NSString*)message
-                                  defaultText:(NSString*)defaultText
-                                   requestURL:(const GURL&)requestURL
-                                     webState:(web::WebState*)webState
-                            completionHandler:
-                                (void (^)(NSString* input))completionHandler {
-  PromptCallback safeCallback =
-      GetSafeJavaScriptPromptCompletion(completionHandler);
-  NSString* title = [DialogPresenter
-      localizedTitleForJavaScriptAlertFromPage:requestURL
-                                  mainFrameURL:webState->GetLastCommittedURL()];
-  InputAlertCoordinator* alertCoordinator = [[InputAlertCoordinator alloc]
-      initWithBaseViewController:self.viewController
-                           title:title
-                         message:message];
-
-  // Actions.
-  __weak InputAlertCoordinator* weakCoordinator = alertCoordinator;
-  ProceduralBlock confirmAction = ^{
-    if (safeCallback) {
-      NSString* textInput = [weakCoordinator textFields].firstObject.text;
-      safeCallback(textInput ? textInput : @"");
-    }
-  };
-
-  ProceduralBlock cancelAction = ^{
-    if (safeCallback)
-      safeCallback(nil);
-  };
-
-  // Coordinator Setup.
-  NSString* OKLabel = l10n_util::GetNSString(IDS_OK);
-  [self setUpAlertCoordinator:alertCoordinator
-                confirmAction:confirmAction
-                 cancelAction:cancelAction
-                      OKLabel:OKLabel];
-
-  // Blocking option setup.
-  [self setUpBlockingOptionForCoordinator:alertCoordinator webState:webState];
-
-  // Add text field.
-  [alertCoordinator
-      addTextFieldWithConfigurationHandler:^(UITextField* textField) {
-        textField.text = defaultText;
-        textField.accessibilityIdentifier =
-            kJavaScriptDialogTextFieldAccessibilityIdentifier;
-      }];
-
-  [self addDialogCoordinator:alertCoordinator forWebState:webState];
-}
-
-- (void)runAuthDialogForProtectionSpace:(NSURLProtectionSpace*)protectionSpace
-                     proposedCredential:(NSURLCredential*)credential
-                               webState:(web::WebState*)webState
-                      completionHandler:(void (^)(NSString* user,
-                                                  NSString* password))handler {
-  HTTPAuthCallack safeCallback = GetSafeHTTPAuthCompletion(handler);
-  NSString* title = l10n_util::GetNSStringWithFixup(IDS_LOGIN_DIALOG_TITLE);
-  NSString* message =
-      nsurlprotectionspace_util::MessageForHTTPAuth(protectionSpace);
-
-  InputAlertCoordinator* alertCoordinator = [[InputAlertCoordinator alloc]
-      initWithBaseViewController:self.viewController
-                           title:title
-                         message:message];
-
-  // Actions.
-  __weak InputAlertCoordinator* weakCoordinator = alertCoordinator;
-  ProceduralBlock confirmAction = ^{
-    if (safeCallback) {
-      NSString* username = [[weakCoordinator textFields] objectAtIndex:0].text;
-      NSString* password = [[weakCoordinator textFields] objectAtIndex:1].text;
-      safeCallback(username, password);
-    }
-  };
-
-  ProceduralBlock cancelAction = ^{
-    if (safeCallback)
-      safeCallback(nil, nil);
-  };
-
-  // Coordinator Setup.
-  NSString* OKLabel =
-      l10n_util::GetNSStringWithFixup(IDS_LOGIN_DIALOG_OK_BUTTON_LABEL);
-  [self setUpAlertCoordinator:alertCoordinator
-                confirmAction:confirmAction
-                 cancelAction:cancelAction
-                      OKLabel:OKLabel];
-
-  // Add text fields.
-  NSString* username = credential.user ? credential.user : @"";
-  [alertCoordinator
-      addTextFieldWithConfigurationHandler:^(UITextField* textField) {
-        textField.text = username;
-        textField.placeholder = l10n_util::GetNSString(
-            IDS_IOS_HTTP_LOGIN_DIALOG_USERNAME_PLACEHOLDER);
-      }];
-  [alertCoordinator
-      addTextFieldWithConfigurationHandler:^(UITextField* textField) {
-        textField.placeholder = l10n_util::GetNSString(
-            IDS_IOS_HTTP_LOGIN_DIALOG_PASSWORD_PLACEHOLDER);
-        textField.secureTextEntry = YES;
-      }];
-
-  [self addDialogCoordinator:alertCoordinator forWebState:webState];
-}
-
-- (void)cancelDialogForWebState:(web::WebState*)webState {
-  BOOL cancelingPresentedDialog = webState == self.presentedDialogWebState;
-  AlertCoordinator* dialogToCancel =
-      cancelingPresentedDialog ? self.presentedDialogCoordinator
-                               : _dialogCoordinatorsForWebStates[webState];
-  DCHECK(!cancelingPresentedDialog || dialogToCancel);
-  [dialogToCancel executeCancelHandler];
-  [dialogToCancel stop];
-
-  if (cancelingPresentedDialog) {
-    DCHECK(_dialogCoordinatorsForWebStates[webState] == nil);
-    // Simulate a button tap to trigger showing the next dialog.
-    [self dialogCoordinatorWasStopped:dialogToCancel];
-  } else if (dialogToCancel) {
-    // Clean up queued state.
-    auto it =
-        std::find(_queuedWebStates.begin(), _queuedWebStates.end(), webState);
-    DCHECK(it != _queuedWebStates.end());
-    webState->RemoveObserver(_webStateObserver.get());
-    _queuedWebStates.erase(it);
-    _dialogCoordinatorsForWebStates.erase(webState);
-  }
-}
-
-- (void)cancelAllDialogs {
-  while (!_queuedWebStates.empty()) {
-    [self cancelDialogForWebState:_queuedWebStates.front()];
-  }
-  if (self.presentedDialogWebState)
-    [self cancelDialogForWebState:self.presentedDialogWebState];
-}
-
-- (void)tryToPresent {
-  // Don't try to present if a JavaScript dialog blocking confirmation sheet is
-  // displayed.
-  if (self.blockingConfirmationCoordinator)
-    return;
-  if (!self.showingDialog && _active && !_queuedWebStates.empty() &&
-      [self.delegate shouldDialogPresenterPresentDialog:self]) {
-    [self showNextDialog];
-  }
-}
-
-+ (NSString*)localizedTitleForJavaScriptAlertFromPage:(const GURL&)pageURL
-                                         mainFrameURL:
-                                             (const GURL&)mainFrameURL {
-  bool sameOriginAsMainFrame = pageURL.GetOrigin() == mainFrameURL.GetOrigin();
-  if (!sameOriginAsMainFrame) {
-    return l10n_util::GetNSString(
-        IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL_IFRAME);
-  }
-  base::string16 title = url_formatter::FormatUrlForSecurityDisplay(
-      pageURL, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
-  return l10n_util::GetNSStringF(IDS_JAVASCRIPT_MESSAGEBOX_TITLE, title);
-}
-
-#pragma mark - CRWWebStateObserver
-
-- (void)webState:(web::WebState*)webState
-    didStartNavigation:(web::NavigationContext*)navigation {
-  [self cancelDialogForWebState:webState];
-}
-
-- (void)webState:(web::WebState*)webState
-    didFinishNavigation:(web::NavigationContext*)navigation {
-  if (navigation->HasCommitted() && !navigation->IsSameDocument())
-    [self cancelDialogForWebState:webState];
-}
-
-- (void)renderProcessGoneForWebState:(web::WebState*)webState {
-  [self cancelDialogForWebState:webState];
-}
-
-- (void)webStateDestroyed:(web::WebState*)webState {
-  [self cancelDialogForWebState:webState];
-  webState->RemoveObserver(_webStateObserver.get());
-}
-
-#pragma mark - Private methods.
-
-- (void)addDialogCoordinator:(AlertCoordinator*)coordinator
-                 forWebState:(web::WebState*)webState {
-  DCHECK(coordinator);
-  DCHECK(webState);
-  DCHECK_NE(webState, self.presentedDialogWebState);
-  DCHECK(!_dialogCoordinatorsForWebStates[webState]);
-  _queuedWebStates.push_back(webState);
-  _dialogCoordinatorsForWebStates[webState] = coordinator;
-
-  webState->AddObserver(_webStateObserver.get());
-
-  if (self.active && !self.showingDialog &&
-      [self.delegate shouldDialogPresenterPresentDialog:self]) {
-    [self showNextDialog];
-  }
-}
-
-- (void)showNextDialog {
-  DCHECK(self.active);
-  DCHECK(!self.showingDialog);
-  DCHECK(!_queuedWebStates.empty());
-  // Update properties and remove context and the dialog from queue.
-  self.presentedDialogWebState = _queuedWebStates.front();
-  _queuedWebStates.pop_front();
-  self.presentedDialogCoordinator =
-      _dialogCoordinatorsForWebStates[self.presentedDialogWebState];
-  _dialogCoordinatorsForWebStates.erase(self.presentedDialogWebState);
-  // Notify the delegate and display the dialog.
-  [self.delegate dialogPresenter:self
-       willShowDialogForWebState:self.presentedDialogWebState];
-  [self.presentedDialogCoordinator start];
-  self.presentedDialogCoordinator.alertController.view.accessibilityIdentifier =
-      kJavaScriptDialogAccessibilityIdentifier;
-}
-
-- (void)dialogCoordinatorWasStopped:(AlertCoordinator*)coordinator {
-  if (coordinator != self.presentedDialogCoordinator)
-    return;
-  self.presentedDialogWebState->RemoveObserver(_webStateObserver.get());
-  self.presentedDialogWebState = nil;
-  self.presentedDialogCoordinator = nil;
-  self.blockingConfirmationCoordinator = nil;
-  if (!_queuedWebStates.empty() &&
-      [self.delegate shouldDialogPresenterPresentDialog:self]) {
-    [self showNextDialog];
-  }
-}
-
-- (void)setUpAlertCoordinator:(AlertCoordinator*)alertCoordinator
-                confirmAction:(ProceduralBlock)confirmAction
-                 cancelAction:(ProceduralBlock)cancelAction
-                      OKLabel:(NSString*)label {
-  // Handlers.
-  __weak DialogPresenter* weakSelf = self;
-  __weak AlertCoordinator* weakCoordinator = alertCoordinator;
-
-  ProceduralBlock confirmHandler = ^{
-    if (confirmAction)
-      confirmAction();
-    [weakSelf dialogCoordinatorWasStopped:weakCoordinator];
-  };
-
-  ProceduralBlock cancelHandler = ^{
-    if (cancelAction)
-      cancelAction();
-    [weakSelf dialogCoordinatorWasStopped:weakCoordinator];
-  };
-
-  // Add buttons.
-  [alertCoordinator addItemWithTitle:label
-                              action:confirmHandler
-                               style:UIAlertActionStyleDefault];
-  [alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL)
-                              action:cancelHandler
-                               style:UIAlertActionStyleCancel];
-
-  // Add cancel handler.
-  alertCoordinator.cancelAction = cancelAction;
-  alertCoordinator.noInteractionAction = cancelAction;
-}
-
-- (void)setUpBlockingOptionForCoordinator:(AlertCoordinator*)alertCoordinator
-                                 webState:(web::WebState*)webState {
-  DCHECK(alertCoordinator);
-  DCHECK(webState);
-
-  JavaScriptDialogBlockingState::CreateForWebState(webState);
-  JavaScriptDialogBlockingState* blockingState =
-      JavaScriptDialogBlockingState::FromWebState(webState);
-
-  // Set up the start action.
-  ProceduralBlock originalStartAction = alertCoordinator.startAction;
-  alertCoordinator.startAction = ^{
-    if (originalStartAction)
-      originalStartAction();
-    blockingState->JavaScriptDialogWasShown();
-  };
-
-  // Early return if a blocking option should not be added.
-  if (!blockingState->show_blocking_option())
-    return;
-
-  ProceduralBlock blockingAction =
-      [self blockingActionForCoordinator:alertCoordinator];
-  NSString* blockingOptionTitle =
-      l10n_util::GetNSString(IDS_IOS_JAVA_SCRIPT_DIALOG_BLOCKING_BUTTON_TEXT);
-  [alertCoordinator addItemWithTitle:blockingOptionTitle
-                              action:blockingAction
-                               style:UIAlertActionStyleDefault];
-}
-
-- (ProceduralBlock)blockingActionForCoordinator:(AlertCoordinator*)coordinator {
-  __weak DialogPresenter* weakSelf = self;
-  __weak AlertCoordinator* weakCoordinator = coordinator;
-  __weak UIViewController* weakBaseViewController =
-      coordinator.baseViewController;
-  ProceduralBlock cancelAction = coordinator.cancelAction;
-  return [^{
-    // Create the confirmation coordinator.  Use an action sheet on iPhone and
-    // an alert on iPhone.
-    NSString* confirmMessage =
-        l10n_util::GetNSString(IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION);
-    AlertCoordinator* confirmationCoordinator =
-        IsIPadIdiom() ? [[AlertCoordinator alloc]
-                            initWithBaseViewController:weakBaseViewController
-                                                 title:nil
-                                               message:confirmMessage]
-                      : [[ActionSheetCoordinator alloc]
-                            initWithBaseViewController:weakBaseViewController
-                                                 title:nil
-                                               message:confirmMessage
-                                                  rect:CGRectZero
-                                                  view:nil];
-    // Set up button actions.
-    ProceduralBlock confirmHandler = ^{
-      if (cancelAction)
-        cancelAction();
-      DialogPresenter* strongSelf = weakSelf;
-      if (!strongSelf)
-        return;
-      web::WebState* webState = [strongSelf presentedDialogWebState];
-      JavaScriptDialogBlockingState::FromWebState(webState)
-          ->JavaScriptDialogBlockingOptionSelected();
-      [strongSelf dialogCoordinatorWasStopped:weakCoordinator];
-    };
-    ProceduralBlock cancelHandler = ^{
-      if (cancelAction)
-        cancelAction();
-      [weakSelf dialogCoordinatorWasStopped:weakCoordinator];
-    };
-    NSString* blockingOptionTitle =
-        l10n_util::GetNSString(IDS_IOS_JAVA_SCRIPT_DIALOG_BLOCKING_BUTTON_TEXT);
-    [confirmationCoordinator addItemWithTitle:blockingOptionTitle
-                                       action:confirmHandler
-                                        style:UIAlertActionStyleDestructive];
-    [confirmationCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL)
-                                       action:cancelHandler
-                                        style:UIAlertActionStyleCancel];
-    [weakSelf setBlockingConfirmationCoordinator:confirmationCoordinator];
-    [[weakSelf blockingConfirmationCoordinator] start];
-  } copy];
-}
-
-@end
diff --git a/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm b/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm
deleted file mode 100644
index 65ba192..0000000
--- a/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm
+++ /dev/null
@@ -1,367 +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.
-
-#import "ios/chrome/browser/ui/dialogs/dialog_presenter.h"
-
-#include "base/observer_list.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "components/strings/grit/components_strings.h"
-#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
-#import "ios/web/public/navigation/navigation_item.h"
-#import "ios/web/public/test/fakes/fake_navigation_context.h"
-#import "ios/web/public/test/fakes/test_navigation_manager.h"
-#import "ios/web/public/test/fakes/test_web_state.h"
-#include "ios/web/public/web_state_observer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "url/gurl.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@interface TestDialogPresenterDelegate : NSObject<DialogPresenterDelegate> {
-  std::vector<web::WebState*> _presentedWebStates;
-}
-// The web states for the dialogs that have been presented.
-@property(nonatomic, readonly) std::vector<web::WebState*>& presentedWebStates;
-// Whether the dialog should be allowed to present a dialog.
-@property(nonatomic, assign) BOOL shouldAllowDialogPresentation;
-@end
-
-@implementation TestDialogPresenterDelegate
-
-- (instancetype)init {
-  if (self = [super init]) {
-    _shouldAllowDialogPresentation = YES;
-  }
-  return self;
-}
-
-- (std::vector<web::WebState*>&)presentedWebStates {
-  return _presentedWebStates;
-}
-
-- (void)dialogPresenter:(DialogPresenter*)presenter
-    willShowDialogForWebState:(web::WebState*)webState {
-  _presentedWebStates.push_back(webState);
-}
-
-- (BOOL)shouldDialogPresenterPresentDialog:(DialogPresenter*)presenter {
-  return self.shouldAllowDialogPresentation;
-}
-
-@end
-
-class DialogPresenterTest : public PlatformTest {
- protected:
-  DialogPresenterTest()
-      : delegate_([[TestDialogPresenterDelegate alloc] init]),
-        viewController_([[UIViewController alloc] init]),
-        presenter_([[DialogPresenter alloc] initWithDelegate:delegate_
-                                    presentingViewController:viewController_]) {
-    [presenter_ setActive:YES];
-  }
-  ~DialogPresenterTest() override {
-    [[presenter_ presentedDialogCoordinator] stop];
-  }
-
-  TestDialogPresenterDelegate* delegate() { return delegate_; }
-  UIViewController* viewController() { return viewController_; }
-  DialogPresenter* presenter() { return presenter_; }
-
- private:
-  TestDialogPresenterDelegate* delegate_;
-  UIViewController* viewController_;
-  DialogPresenter* presenter_;
-};
-
-// Tests that a dialog was successfully shown and that the delegate was notified
-// with the correct context.
-TEST_F(DialogPresenterTest, SimpleTest) {
-  web::TestWebState webState;
-  [presenter() runJavaScriptAlertPanelWithMessage:@""
-                                       requestURL:GURL()
-                                         webState:&webState
-                                completionHandler:nil];
-  EXPECT_EQ(1U, delegate().presentedWebStates.size());
-  EXPECT_EQ(&webState, delegate().presentedWebStates.front());
-}
-
-// Test that javascript dialogs are presented with a different title when they
-// are presented from a URL with a different origin to the webstate origin.
-TEST_F(DialogPresenterTest, IFrameTest) {
-  web::TestWebState web_state;
-  GURL foo_url = GURL("http://foo.com");
-  GURL bar_url = GURL("http://bar.com");
-
-  web_state.SetCurrentURL(foo_url);
-  [presenter() runJavaScriptAlertPanelWithMessage:@""
-                                       requestURL:foo_url
-                                         webState:&web_state
-                                completionHandler:nil];
-
-  // Ensure alerts from the same domain have a correct title.
-  NSString* same_origin_title =
-      [presenter() presentedDialogCoordinator].alertController.title;
-  NSString* hostname = base::SysUTF8ToNSString(foo_url.host());
-  NSString* expected_title = l10n_util::GetNSStringF(
-      IDS_JAVASCRIPT_MESSAGEBOX_TITLE, base::SysNSStringToUTF16(hostname));
-  EXPECT_NSEQ(expected_title, same_origin_title);
-
-  [presenter() cancelAllDialogs];
-
-  // Ensure that alerts from an embedded iframe with a different domain have
-  // a title and it's different to the same-origin title.
-  web_state.SetCurrentURL(bar_url);
-  [presenter() runJavaScriptAlertPanelWithMessage:@""
-                                       requestURL:foo_url
-                                         webState:&web_state
-                                completionHandler:nil];
-  NSString* different_origin_title =
-      [presenter() presentedDialogCoordinator].alertController.title;
-  expected_title = l10n_util::GetNSString(
-      IDS_JAVASCRIPT_MESSAGEBOX_TITLE_NONSTANDARD_URL_IFRAME);
-  EXPECT_NSEQ(expected_title, different_origin_title);
-}
-
-// Tests that JavaScript dialogs have correct title when they are presented from
-// about:blank page.
-TEST_F(DialogPresenterTest, AboutBlankTest) {
-  web::TestWebState web_state;
-  web_state.SetCurrentURL(GURL(url::kAboutBlankURL));
-  [presenter() runJavaScriptAlertPanelWithMessage:@""
-                                       requestURL:GURL(url::kAboutBlankURL)
-                                         webState:&web_state
-                                completionHandler:nil];
-
-  NSString* expected_title = l10n_util::GetNSStringF(
-      IDS_JAVASCRIPT_MESSAGEBOX_TITLE, base::UTF8ToUTF16(url::kAboutBlankURL));
-  NSString* actual_title =
-      [presenter() presentedDialogCoordinator].alertController.title;
-  EXPECT_NSEQ(expected_title, actual_title);
-}
-
-// Tests that multiple JavaScript dialogs are queued
-TEST_F(DialogPresenterTest, QueueTest) {
-  // Tests that the dialog for |webState1| has been shown.
-  web::TestWebState webState1;
-  [presenter() runJavaScriptAlertPanelWithMessage:@""
-                                       requestURL:GURL()
-                                         webState:&webState1
-                                completionHandler:nil];
-  EXPECT_EQ(1U, delegate().presentedWebStates.size());
-  EXPECT_EQ(&webState1, delegate().presentedWebStates.front());
-  // Attempt to present another dialog for |webState2|, and verify that only
-  // |webState2| has been shown.
-  web::TestWebState webState2;
-  [presenter() runJavaScriptAlertPanelWithMessage:@""
-                                       requestURL:GURL()
-                                         webState:&webState2
-                                completionHandler:nil];
-  EXPECT_EQ(1U, delegate().presentedWebStates.size());
-  EXPECT_EQ(&webState1, delegate().presentedWebStates.front());
-  // Dismiss the dialog for |webState1| and call the confirm handler to trigger
-  // showing the dialog for |webState2|.
-  [presenter().presentedDialogCoordinator stop];
-  [presenter()
-      dialogCoordinatorWasStopped:presenter().presentedDialogCoordinator];
-  EXPECT_EQ(2U, delegate().presentedWebStates.size());
-  EXPECT_EQ(&webState1, delegate().presentedWebStates.front());
-  EXPECT_EQ(&webState2, delegate().presentedWebStates.back());
-}
-
-// Tests that cancelling a queued JavaScript dialog will call its completion
-// handler.
-TEST_F(DialogPresenterTest, CancelTest) {
-  // Show a dialog for |webState1| and enqueue a dialog for |webState2|.
-  web::TestWebState webState1;
-  [presenter() runJavaScriptAlertPanelWithMessage:@""
-                                       requestURL:GURL()
-                                         webState:&webState1
-                                completionHandler:nil];
-  web::TestWebState webState2;
-  __block BOOL completion_called = NO;
-  [presenter() runJavaScriptAlertPanelWithMessage:@""
-                                       requestURL:GURL()
-                                         webState:&webState2
-                                completionHandler:^{
-                                  completion_called = YES;
-                                }];
-  EXPECT_EQ(1U, delegate().presentedWebStates.size());
-  EXPECT_EQ(&webState1, delegate().presentedWebStates.front());
-  // Cancel the dialog for |webState2| and verify that |completion_called| was
-  // reset.
-  [presenter() cancelDialogForWebState:&webState2];
-  EXPECT_TRUE(completion_called);
-}
-
-// Tests that if the delegate is presenting, the alert is showed only when
-// notified.
-TEST_F(DialogPresenterTest, DelegatePresenting) {
-  // Tests that the dialog is not shown if the delegate is presenting.
-  web::TestWebState webState1;
-  delegate().shouldAllowDialogPresentation = NO;
-  [presenter() runJavaScriptAlertPanelWithMessage:@""
-                                       requestURL:GURL()
-                                         webState:&webState1
-                                completionHandler:nil];
-  EXPECT_EQ(0U, delegate().presentedWebStates.size());
-  [presenter() tryToPresent];
-  EXPECT_EQ(0U, delegate().presentedWebStates.size());
-
-  // The delegate is not presenting anymore, the dialog is not shown yet.
-  delegate().shouldAllowDialogPresentation = YES;
-  EXPECT_EQ(0U, delegate().presentedWebStates.size());
-
-  // Notify the presenter that it can present.
-  [presenter() tryToPresent];
-  EXPECT_EQ(1U, delegate().presentedWebStates.size());
-  EXPECT_EQ(&webState1, delegate().presentedWebStates.front());
-}
-
-// Tests that cancelling all queued JavaScript dialogs will call all completion
-// handlers.
-TEST_F(DialogPresenterTest, CancelAllTest) {
-  // Show a dialog for |context1| and enqueue a dialog for |context2| and
-  // |context3|.
-  web::TestWebState webState1;
-  __block BOOL completion1_called = NO;
-  [presenter() runJavaScriptAlertPanelWithMessage:@"1"
-                                       requestURL:GURL()
-                                         webState:&webState1
-                                completionHandler:^{
-                                  completion1_called = YES;
-                                }];
-  web::TestWebState webState2;
-  __block BOOL completion2_called = NO;
-  [presenter() runJavaScriptAlertPanelWithMessage:@"2"
-                                       requestURL:GURL()
-                                         webState:&webState2
-                                completionHandler:^{
-                                  completion2_called = YES;
-                                }];
-  web::TestWebState webState3;
-  __block BOOL completion3_called = NO;
-  [presenter() runJavaScriptAlertPanelWithMessage:@"3"
-                                       requestURL:GURL()
-                                         webState:&webState3
-                                completionHandler:^{
-                                  completion3_called = YES;
-                                }];
-  EXPECT_EQ(1U, delegate().presentedWebStates.size());
-  EXPECT_EQ(&webState1, delegate().presentedWebStates.front());
-  // Cancel all dialogs and verify that all |completion_called| were called.
-  [presenter() cancelAllDialogs];
-  EXPECT_TRUE(completion1_called);
-  EXPECT_TRUE(completion2_called);
-  EXPECT_TRUE(completion3_called);
-}
-
-// Tests that dialogs are appropriately cancelled for
-// WebStateObserver::DidStartNavigation().
-TEST_F(DialogPresenterTest, CancelForNavigationStarted) {
-  // Set up a WebState complete with NavigationManager with last commited item.
-  std::unique_ptr<web::NavigationItem> item = web::NavigationItem::Create();
-  item->SetURL(GURL("https://chromium.org"));
-  std::unique_ptr<web::TestNavigationManager> nav_manager =
-      std::make_unique<web::TestNavigationManager>();
-  nav_manager->SetLastCommittedItem(item.get());
-  std::unique_ptr<web::TestWebState> web_state =
-      std::make_unique<web::TestWebState>();
-  web_state->SetNavigationManager(std::move(nav_manager));
-  // Verify cancellation for DidStartNavigation().
-  __block BOOL dialog_cancelled = NO;
-  [presenter() runJavaScriptTextInputPanelWithPrompt:@""
-                                         defaultText:@""
-                                          requestURL:item->GetURL()
-                                            webState:web_state.get()
-                                   completionHandler:^(NSString* input) {
-                                     dialog_cancelled = !input;
-                                   }];
-  web::FakeNavigationContext context;
-  web_state->OnNavigationStarted(&context);
-  EXPECT_TRUE(dialog_cancelled);
-}
-
-// Tests that dialogs are appropriately cancelled for
-// WebStateObserver::DidFinishNavigation().
-TEST_F(DialogPresenterTest, CancelForNavigationFinished) {
-  // Set up a WebState complete with NavigationManager with last commited item.
-  std::unique_ptr<web::NavigationItem> item = web::NavigationItem::Create();
-  item->SetURL(GURL("https://chromium.org"));
-  std::unique_ptr<web::TestNavigationManager> nav_manager =
-      std::make_unique<web::TestNavigationManager>();
-  nav_manager->SetLastCommittedItem(item.get());
-  std::unique_ptr<web::TestWebState> web_state =
-      std::make_unique<web::TestWebState>();
-  web_state->SetNavigationManager(std::move(nav_manager));
-  // Verify cancellation for DidFinishNavigation().
-  __block BOOL dialog_cancelled = NO;
-  [presenter() runJavaScriptTextInputPanelWithPrompt:@""
-                                         defaultText:@""
-                                          requestURL:item->GetURL()
-                                            webState:web_state.get()
-                                   completionHandler:^(NSString* input) {
-                                     dialog_cancelled = !input;
-                                   }];
-  web::FakeNavigationContext context;
-  context.SetHasCommitted(true);
-  web_state->OnNavigationFinished(&context);
-  EXPECT_TRUE(dialog_cancelled);
-}
-
-// Tests that dialogs are appropriately cancelled for
-// WebStateObserver::RenderProcessGone().
-TEST_F(DialogPresenterTest, CancelForRenderProcessGone) {
-  // Set up a WebState complete with NavigationManager with last commited item.
-  std::unique_ptr<web::NavigationItem> item = web::NavigationItem::Create();
-  item->SetURL(GURL("https://chromium.org"));
-  std::unique_ptr<web::TestNavigationManager> nav_manager =
-      std::make_unique<web::TestNavigationManager>();
-  nav_manager->SetLastCommittedItem(item.get());
-  std::unique_ptr<web::TestWebState> web_state =
-      std::make_unique<web::TestWebState>();
-  web_state->SetNavigationManager(std::move(nav_manager));
-  // Verify cancellation for RenderProcessGone().
-  __block BOOL dialog_cancelled = NO;
-  [presenter() runJavaScriptTextInputPanelWithPrompt:@""
-                                         defaultText:@""
-                                          requestURL:item->GetURL()
-                                            webState:web_state.get()
-                                   completionHandler:^(NSString* input) {
-                                     dialog_cancelled = !input;
-                                   }];
-  web_state->OnRenderProcessGone();
-  EXPECT_TRUE(dialog_cancelled);
-}
-
-// Tests that dialogs are appropriately cancelled for
-// WebStateObserver::WebStateDestroyed().
-TEST_F(DialogPresenterTest, CancelForWebStateDestroyed) {
-  // Set up a WebState complete with NavigationManager with last commited item.
-  std::unique_ptr<web::NavigationItem> item = web::NavigationItem::Create();
-  item->SetURL(GURL("https://chromium.org"));
-  std::unique_ptr<web::TestNavigationManager> nav_manager =
-      std::make_unique<web::TestNavigationManager>();
-  nav_manager->SetLastCommittedItem(item.get());
-  std::unique_ptr<web::TestWebState> web_state =
-      std::make_unique<web::TestWebState>();
-  web_state->SetNavigationManager(std::move(nav_manager));
-  // Verify cancellation for WebStateDestroyed().
-  __block BOOL dialog_cancelled = NO;
-  [presenter() runJavaScriptTextInputPanelWithPrompt:@""
-                                         defaultText:@""
-                                          requestURL:item->GetURL()
-                                            webState:web_state.get()
-                                   completionHandler:^(NSString* input) {
-                                     dialog_cancelled = !input;
-                                   }];
-  web_state = nullptr;
-  EXPECT_TRUE(dialog_cancelled);
-}
diff --git a/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.h b/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.h
deleted file mode 100644
index a73d46f..0000000
--- a/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.h
+++ /dev/null
@@ -1,45 +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.
-
-#ifndef IOS_CHROME_BROWSER_UI_DIALOGS_JAVA_SCRIPT_DIALOG_PRESENTER_IMPL_H_
-#define IOS_CHROME_BROWSER_UI_DIALOGS_JAVA_SCRIPT_DIALOG_PRESENTER_IMPL_H_
-
-#include "ios/web/public/ui/java_script_dialog_presenter.h"
-
-@class AlertCoordinator;
-@class DialogPresenter;
-
-// The maximum characters to use for the JavaScript dialog message text.
-extern const size_t kJavaScriptDialogMaxMessageLength;
-
-class JavaScriptDialogPresenterImpl final
-    : public web::JavaScriptDialogPresenter {
- public:
-  explicit JavaScriptDialogPresenterImpl(DialogPresenter* dialogPresenter);
-  ~JavaScriptDialogPresenterImpl() override;
-
-  void RunJavaScriptDialog(web::WebState* web_state,
-                           const GURL& origin_url,
-                           web::JavaScriptDialogType dialog_type,
-                           NSString* message_text,
-                           NSString* default_prompt_text,
-                           web::DialogClosedCallback callback) override;
-
-  void CancelDialogs(web::WebState* web_state) override;
-
-  // JavaScript dialogs presented by this class cap the message text length to
-  // kJavaScriptDialogMaxMessageLength.  This utility function performs that
-  // operation on an input NSString.
-  // TODO(crbug.com/674649): Remove this after switching to custom dialog
-  // implementation.
-  static NSString* GetTruncatedMessageText(NSString* message_text);
-
- private:
-  // The underlying DialogPresenter handling the dialog UI.
-  DialogPresenter* dialog_presenter_;
-
-  DISALLOW_COPY_AND_ASSIGN(JavaScriptDialogPresenterImpl);
-};
-
-#endif  // IOS_CHROME_BROWSER_UI_DIALOGS_JAVA_SCRIPT_DIALOG_PRESENTER_IMPL_H_
diff --git a/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.mm b/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.mm
deleted file mode 100644
index d1e51248..0000000
--- a/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.mm
+++ /dev/null
@@ -1,107 +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 "ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.h"
-
-#include "base/strings/sys_string_conversions.h"
-#import "ios/chrome/browser/ui/dialogs/dialog_presenter.h"
-#import "ios/chrome/browser/ui/dialogs/java_script_dialog_blocking_state.h"
-#include "ios/chrome/browser/ui/dialogs/java_script_dialog_metrics.h"
-#include "ui/gfx/text_elider.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-const size_t kJavaScriptDialogMaxMessageLength = 150;
-
-JavaScriptDialogPresenterImpl::JavaScriptDialogPresenterImpl(
-    DialogPresenter* dialogPresenter)
-    : dialog_presenter_(dialogPresenter) {}
-
-JavaScriptDialogPresenterImpl::~JavaScriptDialogPresenterImpl() {}
-
-void JavaScriptDialogPresenterImpl::RunJavaScriptDialog(
-    web::WebState* web_state,
-    const GURL& origin_url,
-    web::JavaScriptDialogType dialog_type,
-    NSString* message_text,
-    NSString* default_prompt_text,
-    web::DialogClosedCallback callback) {
-  JavaScriptDialogBlockingState::CreateForWebState(web_state);
-  if (JavaScriptDialogBlockingState::FromWebState(web_state)->blocked()) {
-    // Block the dialog if needed.
-    RecordDialogDismissalCause(IOSJavaScriptDialogDismissalCause::kBlocked);
-    std::move(callback).Run(NO, nil);
-    return;
-  }
-  message_text =
-      JavaScriptDialogPresenterImpl::GetTruncatedMessageText(message_text);
-  switch (dialog_type) {
-    case web::JAVASCRIPT_DIALOG_TYPE_ALERT: {
-      __block web::DialogClosedCallback scoped_callback = std::move(callback);
-      [dialog_presenter_
-          runJavaScriptAlertPanelWithMessage:message_text
-                                  requestURL:origin_url
-                                    webState:web_state
-                           completionHandler:^{
-                             RecordDialogDismissalCause(
-                                 IOSJavaScriptDialogDismissalCause::kUser);
-                             if (!scoped_callback.is_null()) {
-                               std::move(scoped_callback).Run(YES, nil);
-                             }
-                           }];
-      break;
-    }
-    case web::JAVASCRIPT_DIALOG_TYPE_CONFIRM: {
-      __block web::DialogClosedCallback scoped_callback = std::move(callback);
-      [dialog_presenter_
-          runJavaScriptConfirmPanelWithMessage:message_text
-                                    requestURL:origin_url
-                                      webState:web_state
-                             completionHandler:^(BOOL is_confirmed) {
-                               RecordDialogDismissalCause(
-                                   IOSJavaScriptDialogDismissalCause::kUser);
-                               if (!scoped_callback.is_null()) {
-                                 std::move(scoped_callback)
-                                     .Run(is_confirmed, nil);
-                               }
-                             }];
-      break;
-    }
-    case web::JAVASCRIPT_DIALOG_TYPE_PROMPT: {
-      __block web::DialogClosedCallback scoped_callback = std::move(callback);
-      [dialog_presenter_
-          runJavaScriptTextInputPanelWithPrompt:message_text
-                                    defaultText:default_prompt_text
-                                     requestURL:origin_url
-                                       webState:web_state
-                              completionHandler:^(NSString* text_input) {
-                                RecordDialogDismissalCause(
-                                    IOSJavaScriptDialogDismissalCause::kUser);
-                                if (!scoped_callback.is_null()) {
-                                  std::move(scoped_callback)
-                                      .Run(YES, text_input);
-                                }
-                              }];
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-void JavaScriptDialogPresenterImpl::CancelDialogs(web::WebState* web_state) {
-  [dialog_presenter_ cancelDialogForWebState:web_state];
-}
-
-// static
-NSString* JavaScriptDialogPresenterImpl::GetTruncatedMessageText(
-    NSString* message_text) {
-  if (message_text.length <= kJavaScriptDialogMaxMessageLength)
-    return message_text;
-  return base::SysUTF16ToNSString(gfx::TruncateString(
-      base::SysNSStringToUTF16(message_text), kJavaScriptDialogMaxMessageLength,
-      gfx::CHARACTER_BREAK));
-}
diff --git a/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl_unittest.mm b/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl_unittest.mm
deleted file mode 100644
index b4dd654..0000000
--- a/ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl_unittest.mm
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ui/dialogs/java_script_dialog_presenter_impl.h"
-
-#import <Foundation/Foundation.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-using JavaScriptDialogPresenterImplTest = PlatformTest;
-
-// Tests that GetTruncatedMessageText() correctly truncates the length of a
-// string to the expected length.
-TEST_F(JavaScriptDialogPresenterImplTest, GetTruncatedMessageText) {
-  NSMutableString* text = [@"text" mutableCopy];
-  while (text.length < kJavaScriptDialogMaxMessageLength) {
-    [text appendString:text];
-  }
-  ASSERT_GT(text.length, kJavaScriptDialogMaxMessageLength);
-  EXPECT_EQ(JavaScriptDialogPresenterImpl::GetTruncatedMessageText(text).length,
-            kJavaScriptDialogMaxMessageLength);
-}
diff --git a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
index 5cbd472..aaa2cd8a 100644
--- a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
+++ b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
@@ -11,7 +11,6 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/elide_url.h"
 #import "ios/chrome/browser/ui/dialogs/dialog_constants.h"
-#import "ios/chrome/browser/ui/dialogs/dialog_features.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
@@ -45,11 +44,6 @@
 
 namespace {
 
-// Whether non-modal dialogs are being used.
-bool AreDialogsNonModal() {
-  return base::FeatureList::IsEnabled(dialogs::kNonModalDialogs);
-}
-
 // Body script for test page that shows an alert with kAlertMessage and returns
 // kAlertResult.
 const char kAlertURLPath[] = "/alert";
@@ -187,24 +181,6 @@
   return GetHttpResponseWithContent(GetLinkPageContents(on_load_page_url));
 }
 
-// Assert that an alert with |alert_text| has been shown or hidden.
-void WaitForAlertWithText(NSString* alert_text, bool visible) {
-  ConditionBlock condition = ^{
-    NSError* error = nil;
-    id<GREYMatcher> text_matcher =
-        chrome_test_util::StaticTextWithAccessibilityLabel(alert_text);
-    [[EarlGrey selectElementWithMatcher:text_matcher]
-        assertWithMatcher:visible ? grey_notNil() : grey_nil()
-                    error:&error];
-    return !error;
-  };
-  NSString* error_text_format = visible
-                                    ? @"Dialog with text was not shown: %@"
-                                    : @"Dialog with text was not hidden: %@";
-  GREYAssert(WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, condition),
-             error_text_format, alert_text);
-}
-
 // Waits for a JavaScript dialog from |url| with |message| to be shown or
 // hidden.
 void WaitForJavaScriptDialog(const GURL& url,
@@ -228,7 +204,7 @@
              error_text);
 
   // Check the title.  Non-modal main-frame dialogs do not have a title label.
-  if (!AreDialogsNonModal() || !is_main_frame) {
+  if (!is_main_frame) {
     base::string16 url_string = url_formatter::FormatUrlForSecurityDisplay(
         url, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
     NSString* expected_title =
@@ -469,18 +445,6 @@
   WaitForJavaScriptDialog(kURL, kAlertLoopMessage, /*visible=*/false,
                           /*is_main_frame=*/true);
 
-  // Modal dialogs have an additional action sheet for dialog suppression.
-  if (!AreDialogsNonModal()) {
-    // Wait for confirmation action sheet to be shown.
-    NSString* alertLabel =
-        l10n_util::GetNSString(IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION);
-    WaitForAlertWithText(alertLabel, /*visible=*/true);
-
-    // Tap the suppress dialogs confirmation button.
-    TapSuppressDialogsButton();
-    WaitForAlertWithText(alertLabel, /*visible=*/false);
-  }
-
   // Wait for the html  to be reset to the loop finished text.
   [ChromeEarlGrey waitForWebStateContainingText:kAlertLoopFinishedText];
 }
@@ -509,12 +473,6 @@
   // Tap the link to trigger the dialog.
   [ChromeEarlGrey tapWebStateElementWithID:@(kTestPageLinkID)];
 
-  // Make sure the alert is not presented modally over settings.
-  if (!AreDialogsNonModal()) {
-    WaitForJavaScriptDialog(kURL, kAlertMessage, /*visible=*/false,
-                            /*is_main_frame=*/true);
-  }
-
   // Close the settings.
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -562,64 +520,4 @@
   [ChromeEarlGrey waitForWebStateContainingText:kAlertResult];
 }
 
-// Tests that an alert is presented after a new tab animation is finished.
-- (void)testShowJavaScriptAfterNewTabAnimation {
-  // TODO(crbug.com/1007986) Test flaky on iOS13.
-  if (@available(iOS 13, *)) {
-    EARL_GREY_TEST_DISABLED(@"Test disabled on iOS13.");
-  }
-
-  // This tests is for DialogPresenter behavior, and does not apply to
-  // OverlayPresenter, which is used for the non-modal dialog solution.
-  if (AreDialogsNonModal()) {
-    EARL_GREY_TEST_DISABLED(@"Test disabled for non-modal dialogs.");
-  }
-
-  // Load the test page with a link to kOnLoadAlertURL and long tap on the link.
-  const GURL kURL = self.testServer->GetURL(kLinkPageURLPath);
-  [ChromeEarlGrey loadURL:kURL];
-  [ChromeEarlGrey waitForWebStateContainingText:kLinkPageLinkText];
-
-  // TODO(crbug.com/712358): Use method LongPressElementAndTapOnButton once
-  // it is moved out of context_menu_egtests.mm and into a shared location.
-  [[EarlGrey selectElementWithMatcher:WebViewMatcher()]
-      performAction:chrome_test_util::LongPressElementForContextMenu(
-                        [ElementSelector selectorWithElementID:kLinkID],
-                        true /* menu should appear */)];
-
-  // Tap on the "Open In New Tab" button.
-  id<GREYMatcher> newTabMatcher = ButtonWithAccessibilityLabel(
-      l10n_util::GetNSStringWithFixup(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB));
-  [[EarlGrey selectElementWithMatcher:newTabMatcher] performAction:grey_tap()];
-
-  // This test case requires that a dialog is presented in the onload event so
-  // that the DialogPresenter attempts to display during a new tab animation.
-  // Because presenting a dialog halts the JavaScript execution on the page,
-  // this prevents the page loaded event from being received until the alert is
-  // closed.  On iPad, this means that there is a loading indicator that
-  // continues to animate until the dialog is closed.  Disabling EarlGrey
-  // synchronization code for iPad allows the test to detect and dismiss the
-  // dialog while this animation is occurring.
-  {
-    std::unique_ptr<ScopedSynchronizationDisabler> disabler =
-        std::make_unique<ScopedSynchronizationDisabler>();
-    if (![ChromeEarlGrey isIPadIdiom]) {
-      disabler.reset();
-    }
-
-    // Wait for the alert to be shown.
-    GURL kOnLoadURL = self.testServer->GetURL(kOnLoadURLPath);
-    WaitForJavaScriptDialog(kURL, kOnLoadAlertMessage, /*visible=*/true,
-                            /*is_main_frame=*/true);
-
-    // Verify that the omnibox shows the correct URL when the dialog is visible.
-    std::string title =
-        base::SysNSStringToUTF8([ChromeEarlGrey displayTitleForURL:kOnLoadURL]);
-    [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(title)]
-        assertWithMatcher:grey_notNil()];
-
-    [[EarlGrey selectElementWithMatcher:OKButton()] performAction:grey_tap()];
-  }
-}
-
 @end
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn
index e5eb7eed..7922933 100644
--- a/ios/chrome/browser/ui/main/BUILD.gn
+++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -116,7 +116,6 @@
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/tabs:tabs_internal",
     "//ios/chrome/browser/ui/alert_coordinator",
-    "//ios/chrome/browser/ui/app_launcher",
     "//ios/chrome/browser/ui/autofill",
     "//ios/chrome/browser/ui/browser_container",
     "//ios/chrome/browser/ui/browser_view",
diff --git a/ios/chrome/credential_provider_extension/strings/resources/ios_credential_provider_extension_strings_bn.xtb b/ios/chrome/credential_provider_extension/strings/resources/ios_credential_provider_extension_strings_bn.xtb
index a7c8ee4..717bd5f5 100644
--- a/ios/chrome/credential_provider_extension/strings/resources/ios_credential_provider_extension_strings_bn.xtb
+++ b/ios/chrome/credential_provider_extension/strings/resources/ios_credential_provider_extension_strings_bn.xtb
@@ -7,11 +7,14 @@
 <translation id="3378542047369517508">Chrome-এ আপনার সেভ করা সব পাসওয়ার্ড অ্যাক্সেস করুন। যেকোনও অ্যাপে। যেকোনও সময়।</translation>
 <translation id="3660601625129812825">Chrome-এর অটোফিল পাসওয়ার্ড</translation>
 <translation id="4695654165345019650">পাসওয়ার্ড অ্যাক্সেস...</translation>
+<translation id="5178539339249989017">সার্চের কোনও ফলাফল পাওয়া যায়নি</translation>
 <translation id="5313485577007399362">অটোফিল চালু করুন...</translation>
 <translation id="6494101196118320406">Chrome-এ কোনও পাসওয়ার্ড নেই</translation>
 <translation id="6846906712230932330">পাসওয়ার্ড ব্যবহার করার জন্য আপনার ডিভাইসে আপনাকে অবশ্যই একটি পাসকোড সেট করতে হবে।</translation>
 <translation id="6965382102122355670">ঠিক আছে</translation>
 <translation id="7870350829250847712">Chrome-এ কোনও পাসওয়ার্ড নেই</translation>
+<translation id="8208791657167738630">সবকটি পাসওয়ার্ড</translation>
 <translation id="8602573493531049509">কীভাবে করবেন জানুন</translation>
+<translation id="8982444110803529242">সাজেস্ট করা পাসওয়ার্ডগুলি</translation>
 <translation id="9087836967653912639">বাতিল করুন</translation>
 </translationbundle>
\ No newline at end of file
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 8b7662f4..b447b3faa 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -226,7 +226,6 @@
     "//ios/chrome/browser/ui/activity_services:unit_tests",
     "//ios/chrome/browser/ui/alert_coordinator:unit_tests",
     "//ios/chrome/browser/ui/alert_view:unit_tests",
-    "//ios/chrome/browser/ui/app_launcher:unit_tests",
     "//ios/chrome/browser/ui/authentication:unit_tests",
     "//ios/chrome/browser/ui/authentication/cells:unit_tests",
     "//ios/chrome/browser/ui/authentication/signin:unit_tests",
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller.mm b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
index 9cca322a..d436b6c 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_controller.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
@@ -50,7 +50,6 @@
 #include "ios/web_view/internal/signin/web_view_identity_manager_factory.h"
 #import "ios/web_view/internal/sync/web_view_profile_sync_service_factory.h"
 #include "ios/web_view/internal/web_view_browser_state.h"
-#include "ios/web_view/internal/webdata_services/web_view_web_data_service_wrapper_factory.h"
 #import "ios/web_view/public/cwv_autofill_controller_delegate.h"
 
 @interface CWVAutofillController ()<AutofillDriverIOSBridge,
@@ -150,9 +149,6 @@
             browserState->GetRecordingBrowserState()),
         ios_web_view::WebViewStrikeDatabaseFactory::GetForBrowserState(
             browserState->GetRecordingBrowserState()),
-        ios_web_view::WebViewWebDataServiceWrapperFactory::
-            GetAutofillWebDataForBrowserState(
-                browserState, ServiceAccessType::EXPLICIT_ACCESS),
         ios_web_view::WebViewProfileSyncServiceFactory::GetForBrowserState(
             browserState)));
     autofill::AutofillDriverIOS::PrepareForWebStateWebFrameAndDelegate(
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.h b/ios/web_view/internal/autofill/web_view_autofill_client_ios.h
index 772215b..60eb50d 100644
--- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.h
+++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.h
@@ -39,7 +39,6 @@
       id<CWVAutofillClientIOSBridge> bridge,
       signin::IdentityManager* identity_manager,
       StrikeDatabase* strike_database,
-      scoped_refptr<AutofillWebDataService> autofill_web_data_service,
       syncer::SyncService* sync_service);
   ~WebViewAutofillClientIOS() override;
 
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
index 0061630..5e864f19 100644
--- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
+++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
@@ -35,7 +35,6 @@
     id<CWVAutofillClientIOSBridge> bridge,
     signin::IdentityManager* identity_manager,
     StrikeDatabase* strike_database,
-    scoped_refptr<AutofillWebDataService> autofill_web_data_service,
     syncer::SyncService* sync_service)
     : pref_service_(pref_service),
       personal_data_manager_(personal_data_manager),
@@ -56,7 +55,6 @@
           ios_web_view::ApplicationContext::GetInstance()
               ->GetApplicationLocale())),
       strike_database_(strike_database),
-      autofill_web_data_service_(autofill_web_data_service),
       sync_service_(sync_service),
       // TODO(crbug.com/928595): Replace the closure with a callback to the
       // renderer that indicates if log messages should be sent from the
@@ -264,7 +262,7 @@
 }
 
 bool WebViewAutofillClientIOS::IsAutocompleteEnabled() {
-  return prefs::IsAutocompleteEnabled(GetPrefs());
+  return false;
 }
 
 void WebViewAutofillClientIOS::PropagateAutofillPredictions(
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index e53b3381..b5dca3b 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -76,9 +76,6 @@
 const char kForceProtectedVideoOutputBuffers[] =
     "force-protected-video-output-buffers";
 
-// Enables fuchsia.media.AudioConsumer to be used to render audio streams.
-const char kEnableFuchsiaAudioConsumer[] = "enable-fuchsia-audio-consumer";
-
 #endif  // defined(OS_FUCHSIA)
 
 #if defined(USE_CRAS)
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 98bb20b..4239d51a0 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -52,7 +52,6 @@
 #if defined(OS_FUCHSIA)
 MEDIA_EXPORT extern const char kEnableProtectedVideoBuffers[];
 MEDIA_EXPORT extern const char kForceProtectedVideoOutputBuffers[];
-MEDIA_EXPORT extern const char kEnableFuchsiaAudioConsumer[];
 #endif
 
 #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION)
diff --git a/media/gpu/chromeos/platform_video_frame_utils_unittest.cc b/media/gpu/chromeos/platform_video_frame_utils_unittest.cc
index 005b9dd..abcc363 100644
--- a/media/gpu/chromeos/platform_video_frame_utils_unittest.cc
+++ b/media/gpu/chromeos/platform_video_frame_utils_unittest.cc
@@ -70,7 +70,7 @@
 class FakeGpuMemoryBufferFactory : public gpu::GpuMemoryBufferFactory {
  public:
   FakeGpuMemoryBufferFactory() = default;
-  ~FakeGpuMemoryBufferFactory() {
+  ~FakeGpuMemoryBufferFactory() override {
     for (const auto& buffers : gpu_memory_buffers_) {
       if (!buffers.second.empty()) {
         LOG(ERROR) << "client_id=" << buffers.first
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.cc b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
index 30fc6d3..bbb0d1a 100644
--- a/media/gpu/windows/dxva_video_decode_accelerator_win.cc
+++ b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
@@ -437,6 +437,8 @@
   // Returns false on failure.
   bool DetectConfig(const uint8_t* stream, unsigned int size) override {
     parser_.SetStream(stream, size, nullptr);
+    config_changed_ = false;
+
     Vp9FrameHeader fhdr;
     gfx::Size allocate_size;
     std::unique_ptr<DecryptConfig> null_config;
@@ -494,11 +496,17 @@
   // Detects stream configuration changes.
   // Returns false on failure.
   bool DetectConfig(const uint8_t* stream, unsigned int size) override {
+    config_changed_ = false;
+
     Vp8FrameHeader fhdr;
     if (!parser_.ParseFrame(stream, size, &fhdr))
       return false;
 
-    if (fhdr.IsKeyframe() && fhdr.is_full_range) {
+    // VP8 parser only return resolution and range fields on key frames.
+    if (!fhdr.IsKeyframe())
+      return true;
+
+    if (fhdr.is_full_range) {
       // VP8 has no color space information, only the range. We will always
       // prefer the config color space if set, but indicate JPEG when the full
       // range flag is set on the frame header.
@@ -507,22 +515,12 @@
 
     // Does VP8 need a separate visible rect?
     gfx::Size new_size(fhdr.width, fhdr.height);
-    if (!size_.IsEmpty() && !pending_config_changed_ && !config_changed_ &&
-        size_ != new_size) {
-      pending_config_changed_ = true;
+    if (!size_.IsEmpty() && size_ != new_size) {
+      config_changed_ = true;
       DVLOG(1) << "Configuration changed from " << size_.ToString() << " to "
                << new_size.ToString();
     }
     size_ = new_size;
-
-    // Resolution changes can happen on any frame technically, so wait for a
-    // keyframe before signaling the config change.
-    if (fhdr.IsKeyframe() && pending_config_changed_) {
-      config_changed_ = true;
-      pending_config_changed_ = false;
-    }
-    if (pending_config_changed_)
-      DVLOG(3) << "Deferring config change until next keyframe...";
     return true;
   }
 
@@ -539,7 +537,6 @@
 
  private:
   gfx::Size size_;
-  bool pending_config_changed_ = false;
   VideoColorSpace color_space_;
   Vp8Parser parser_;
 };
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index f076703..60f1e486 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -45,7 +45,6 @@
 #include "net/quic/quic_chromium_connection_helper.h"
 #include "net/quic/quic_chromium_packet_reader.h"
 #include "net/quic/quic_chromium_packet_writer.h"
-#include "net/quic/quic_client_session_cache.h"
 #include "net/quic/quic_context.h"
 #include "net/quic/quic_crypto_client_stream_factory.h"
 #include "net/quic/quic_http_stream.h"
@@ -325,9 +324,8 @@
  public:
   QuicCryptoClientConfigOwner(
       std::unique_ptr<quic::ProofVerifier> proof_verifier,
-      std::unique_ptr<QuicClientSessionCache> session_cache,
       QuicStreamFactory* quic_stream_factory)
-      : config_(std::move(proof_verifier), std::move(session_cache)),
+      : config_(std::move(proof_verifier)),
         quic_stream_factory_(quic_stream_factory) {
     DCHECK(quic_stream_factory_);
   }
@@ -2279,7 +2277,7 @@
               cert_verifier_, ct_policy_enforcer_, transport_security_state_,
               cert_transparency_verifier_,
               HostsFromOrigins(params_.origins_to_force_quic_on)),
-          std::make_unique<QuicClientSessionCache>(), this);
+          this);
 
   quic::QuicCryptoClientConfig* crypto_config = crypto_config_owner->config();
   crypto_config->set_user_agent_id(params_.user_agent_id);
diff --git a/services/network/trust_tokens/BUILD.gn b/services/network/trust_tokens/BUILD.gn
index 61a7b5b1..bb2273c7 100644
--- a/services/network/trust_tokens/BUILD.gn
+++ b/services/network/trust_tokens/BUILD.gn
@@ -15,6 +15,8 @@
   defines = [ "IS_NETWORK_SERVICE_IMPL" ]
 
   sources = [
+    "ed25519_trust_token_request_signer.cc",
+    "ed25519_trust_token_request_signer.h",
     "has_trust_tokens_answerer.cc",
     "has_trust_tokens_answerer.h",
     "in_memory_trust_token_persister.cc",
@@ -98,6 +100,7 @@
   defines = [ "IS_NETWORK_SERVICE_IMPL" ]
 
   sources = [
+    "ed25519_trust_token_request_signer_unittest.cc",
     "has_trust_tokens_answerer_unittest.cc",
     "pending_trust_token_store_unittest.cc",
     "sqlite_trust_token_persister_unittest.cc",
diff --git a/services/network/trust_tokens/ed25519_trust_token_request_signer.cc b/services/network/trust_tokens/ed25519_trust_token_request_signer.cc
new file mode 100644
index 0000000..cce9801f
--- /dev/null
+++ b/services/network/trust_tokens/ed25519_trust_token_request_signer.cc
@@ -0,0 +1,41 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/trust_tokens/ed25519_trust_token_request_signer.h"
+
+#include "third_party/boringssl/src/include/openssl/curve25519.h"
+
+namespace network {
+
+Ed25519TrustTokenRequestSigner::Ed25519TrustTokenRequestSigner() = default;
+Ed25519TrustTokenRequestSigner::~Ed25519TrustTokenRequestSigner() = default;
+
+base::Optional<std::vector<uint8_t>> Ed25519TrustTokenRequestSigner::Sign(
+    base::span<const uint8_t> key,
+    base::span<const uint8_t> data) {
+  if (key.size() != ED25519_PRIVATE_KEY_LEN)
+    return base::nullopt;
+
+  std::vector<uint8_t> ret(ED25519_SIGNATURE_LEN);
+
+  if (!ED25519_sign(ret.data(), data.data(), data.size(), key.data()))
+    return base::nullopt;
+
+  return ret;
+}
+
+bool Ed25519TrustTokenRequestSigner::Verify(
+    base::span<const uint8_t> data,
+    base::span<const uint8_t> signature,
+    base::span<const uint8_t> verification_key) {
+  if (signature.size() != ED25519_SIGNATURE_LEN)
+    return false;
+  if (verification_key.size() != ED25519_PUBLIC_KEY_LEN)
+    return false;
+
+  return ED25519_verify(data.data(), data.size(), signature.data(),
+                        verification_key.data());
+}
+
+}  // namespace network
diff --git a/services/network/trust_tokens/ed25519_trust_token_request_signer.h b/services/network/trust_tokens/ed25519_trust_token_request_signer.h
new file mode 100644
index 0000000..c8e7521
--- /dev/null
+++ b/services/network/trust_tokens/ed25519_trust_token_request_signer.h
@@ -0,0 +1,33 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_TRUST_TOKENS_ED25519_TRUST_TOKEN_REQUEST_SIGNER_H_
+#define SERVICES_NETWORK_TRUST_TOKENS_ED25519_TRUST_TOKEN_REQUEST_SIGNER_H_
+
+#include "services/network/trust_tokens/trust_token_request_signing_helper.h"
+
+namespace network {
+
+// Ed25519TrustTokenRequestSigner provides a wrapper around BoringSSL's Ed25519
+// signing and verification routines capable of satisfying the Trust Tokens
+// signing request helper's Signer delegate interface.
+class Ed25519TrustTokenRequestSigner
+    : public TrustTokenRequestSigningHelper::Signer {
+ public:
+  Ed25519TrustTokenRequestSigner();
+  ~Ed25519TrustTokenRequestSigner() override;
+
+  // TrustTokenRequestSigningHelper::Signer implementation:
+  base::Optional<std::vector<uint8_t>> Sign(
+      base::span<const uint8_t> key,
+      base::span<const uint8_t> data) override;
+
+  bool Verify(base::span<const uint8_t> data,
+              base::span<const uint8_t> signature,
+              base::span<const uint8_t> verification_key) override;
+};
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_TRUST_TOKENS_ED25519_TRUST_TOKEN_REQUEST_SIGNER_H_
diff --git a/services/network/trust_tokens/ed25519_trust_token_request_signer_unittest.cc b/services/network/trust_tokens/ed25519_trust_token_request_signer_unittest.cc
new file mode 100644
index 0000000..ecd09a8
--- /dev/null
+++ b/services/network/trust_tokens/ed25519_trust_token_request_signer_unittest.cc
@@ -0,0 +1,216 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/trust_tokens/ed25519_trust_token_request_signer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/boringssl/src/include/openssl/curve25519.h"
+
+namespace network {
+
+namespace {
+
+struct Keys {
+  std::array<uint8_t, ED25519_PRIVATE_KEY_LEN> signing;
+  std::array<uint8_t, ED25519_PUBLIC_KEY_LEN> verification;
+};
+
+// The fixed constant 32 comes from curve25519.h and is not defined in a macro.
+Keys KeysFromSeed(base::span<const uint8_t, 32> seed) {
+  Keys ret;
+
+  // Cannot fail.
+  ED25519_keypair_from_seed(ret.verification.data(), ret.signing.data(),
+                            seed.data());
+
+  return ret;
+}
+
+const char kLongishMessage[] =
+    "Four score and seven years ago our fathers brought forth on this "
+    "continent, a new nation, conceived in Liberty, and dedicated to the "
+    "proposition that all men are created equal.";
+
+}  // namespace
+
+TEST(Ed25519TrustTokenRequestSigner, Roundtrip) {
+  auto message = base::as_bytes(base::make_span(kLongishMessage));
+
+  std::array<uint8_t, 32> seed{1, 2, 3, 4, 5};
+  Keys keys = KeysFromSeed(seed);
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(keys.signing, message);
+  ASSERT_TRUE(signature);
+
+  EXPECT_TRUE(signer.Verify(message, *signature, keys.verification));
+}
+
+TEST(Ed25519TrustTokenRequestSigner, EmptyMessage) {
+  auto message = base::span<const uint8_t>();
+
+  std::array<uint8_t, 32> seed{1, 2, 3, 4, 5};
+  Keys keys = KeysFromSeed(seed);
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(keys.signing, message);
+  ASSERT_TRUE(signature);
+
+  EXPECT_TRUE(signer.Verify(message, *signature, keys.verification));
+}
+
+TEST(Ed25519TrustTokenRequestSigner, ShortMessage) {
+  auto message = base::as_bytes(base::make_span("Hello"));
+
+  std::array<uint8_t, 32> seed{1, 2, 3, 4, 5};
+  Keys keys = KeysFromSeed(seed);
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(keys.signing, message);
+  ASSERT_TRUE(signature);
+
+  EXPECT_TRUE(signer.Verify(message, *signature, keys.verification));
+}
+
+TEST(Ed25519TrustTokenRequestSigner, LongerMessage) {
+  std::vector<uint8_t> message(1000000);
+  std::array<uint8_t, 32> seed{1, 2, 3, 4, 5};
+  Keys keys = KeysFromSeed(seed);
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(keys.signing, message);
+  ASSERT_TRUE(signature);
+
+  EXPECT_TRUE(signer.Verify(message, *signature, keys.verification));
+}
+
+TEST(Ed25519TrustTokenRequestSigner, VerificationFromDifferentSigner) {
+  // Test that Verify works without prior initialization and signing, as its
+  // contract promises.
+  auto message = base::as_bytes(base::make_span(kLongishMessage));
+
+  std::array<uint8_t, 32> seed{1, 2, 3, 4, 5};
+  Keys keys = KeysFromSeed(seed);
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(keys.signing, message);
+
+  Ed25519TrustTokenRequestSigner verifier;
+  EXPECT_TRUE(verifier.Verify(message, *signature, keys.verification));
+}
+
+TEST(Ed25519TrustTokenRequestSigner, SigningKeyTooShort) {
+  auto message = base::as_bytes(base::make_span(kLongishMessage));
+
+  std::array<uint8_t, 32> seed{1, 2, 3, 4, 5};
+  Keys keys = KeysFromSeed(seed);
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(base::make_span(keys.signing).subspan(1), message);
+  EXPECT_FALSE(signature);
+}
+
+TEST(Ed25519TrustTokenRequestSigner, SigningKeyTooLong) {
+  auto message = base::as_bytes(base::make_span(kLongishMessage));
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  std::vector<uint8_t> overlong_signing_key(ED25519_PRIVATE_KEY_LEN + 1);
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(overlong_signing_key, message);
+  EXPECT_FALSE(signature);
+}
+
+TEST(Ed25519TrustTokenRequestSigner, VerificationKeyTooShort) {
+  auto message = base::as_bytes(base::make_span(kLongishMessage));
+
+  std::array<uint8_t, 32> seed{1, 2, 3, 4, 5};
+  Keys keys = KeysFromSeed(seed);
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(keys.signing, message);
+
+  EXPECT_FALSE(signer.Verify(message, *signature,
+                             base::make_span(keys.verification).subspan(1)));
+}
+
+TEST(Ed25519TrustTokenRequestSigner, VerificationKeyTooLong) {
+  auto message = base::as_bytes(base::make_span(kLongishMessage));
+
+  std::array<uint8_t, 32> seed{1, 2, 3, 4, 5};
+  Keys keys = KeysFromSeed(seed);
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(keys.signing, message);
+
+  std::vector<uint8_t> overlong_verification_key(ED25519_PUBLIC_KEY_LEN + 1);
+
+  EXPECT_FALSE(signer.Verify(message, *signature, overlong_verification_key));
+}
+
+TEST(Ed25519TrustTokenRequestSigner, SignatureTooShort) {
+  auto message = base::as_bytes(base::make_span(kLongishMessage));
+
+  std::array<uint8_t, 32> seed{1, 2, 3, 4, 5};
+  Keys keys = KeysFromSeed(seed);
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(keys.signing, message);
+  signature->pop_back();
+
+  EXPECT_FALSE(signer.Verify(message, *signature, keys.verification));
+}
+
+TEST(Ed25519TrustTokenRequestSigner, SignatureTooLong) {
+  auto message = base::as_bytes(base::make_span(kLongishMessage));
+
+  std::array<uint8_t, 32> seed{1, 2, 3, 4, 5};
+  Keys keys = KeysFromSeed(seed);
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(keys.signing, message);
+  signature->push_back(0);
+
+  EXPECT_FALSE(
+      signer.Verify(message, base::make_span(*signature), keys.verification));
+}
+
+TEST(Ed25519TrustTokenRequestSigner, SignatureWrong) {
+  auto message = base::as_bytes(base::make_span(kLongishMessage));
+
+  std::array<uint8_t, 32> seed{1, 2, 3, 4, 5};
+  Keys keys = KeysFromSeed(seed);
+
+  Ed25519TrustTokenRequestSigner signer;
+
+  base::Optional<std::vector<uint8_t>> signature =
+      signer.Sign(keys.signing, message);
+
+  // Corrupt the signature.
+  signature->front() += 1;
+
+  EXPECT_FALSE(signer.Verify(message, *signature, keys.verification));
+}
+
+}  // namespace network
diff --git a/services/network/trust_tokens/in_memory_trust_token_persister.cc b/services/network/trust_tokens/in_memory_trust_token_persister.cc
index 10c66dce5..c220f0b 100644
--- a/services/network/trust_tokens/in_memory_trust_token_persister.cc
+++ b/services/network/trust_tokens/in_memory_trust_token_persister.cc
@@ -10,7 +10,8 @@
 InMemoryTrustTokenPersister::~InMemoryTrustTokenPersister() = default;
 
 std::unique_ptr<TrustTokenToplevelConfig>
-InMemoryTrustTokenPersister::GetToplevelConfig(const url::Origin& toplevel) {
+InMemoryTrustTokenPersister::GetToplevelConfig(
+    const SuitableTrustTokenOrigin& toplevel) {
   auto it = toplevel_configs_.find(toplevel);
   if (it == toplevel_configs_.end())
     return nullptr;
@@ -18,7 +19,8 @@
 }
 
 std::unique_ptr<TrustTokenIssuerConfig>
-InMemoryTrustTokenPersister::GetIssuerConfig(const url::Origin& issuer) {
+InMemoryTrustTokenPersister::GetIssuerConfig(
+    const SuitableTrustTokenOrigin& issuer) {
   auto it = issuer_configs_.find(issuer);
   if (it == issuer_configs_.end())
     return nullptr;
@@ -27,8 +29,8 @@
 
 std::unique_ptr<TrustTokenIssuerToplevelPairConfig>
 InMemoryTrustTokenPersister::GetIssuerToplevelPairConfig(
-    const url::Origin& issuer,
-    const url::Origin& toplevel) {
+    const SuitableTrustTokenOrigin& issuer,
+    const SuitableTrustTokenOrigin& toplevel) {
   auto it =
       issuer_toplevel_pair_configs_.find(std::make_pair(issuer, toplevel));
   if (it == issuer_toplevel_pair_configs_.end())
@@ -37,23 +39,45 @@
 }
 
 void InMemoryTrustTokenPersister::SetToplevelConfig(
-    const url::Origin& toplevel,
+    const SuitableTrustTokenOrigin& toplevel,
     std::unique_ptr<TrustTokenToplevelConfig> config) {
   toplevel_configs_[toplevel] = std::move(config);
 }
 
 void InMemoryTrustTokenPersister::SetIssuerConfig(
-    const url::Origin& issuer,
+    const SuitableTrustTokenOrigin& issuer,
     std::unique_ptr<TrustTokenIssuerConfig> config) {
   issuer_configs_[issuer] = std::move(config);
 }
 
 void InMemoryTrustTokenPersister::SetIssuerToplevelPairConfig(
-    const url::Origin& issuer,
-    const url::Origin& toplevel,
+    const SuitableTrustTokenOrigin& issuer,
+    const SuitableTrustTokenOrigin& toplevel,
     std::unique_ptr<TrustTokenIssuerToplevelPairConfig> config) {
   issuer_toplevel_pair_configs_[std::make_pair(issuer, toplevel)] =
       std::move(config);
 }
 
+bool InMemoryTrustTokenPersister::DeleteForOrigins(
+    base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)> matcher) {
+  bool deleted_any_data = false;
+
+  auto predicate_for_origin_keyed_maps = [&matcher](const auto& entry) {
+    return matcher.Run(entry.first);
+  };
+  deleted_any_data |=
+      base::EraseIf(issuer_configs_, predicate_for_origin_keyed_maps);
+  deleted_any_data |=
+      base::EraseIf(toplevel_configs_, predicate_for_origin_keyed_maps);
+
+  deleted_any_data |= base::EraseIf(
+      issuer_toplevel_pair_configs_, [&matcher](const auto& entry) {
+        const std::pair<SuitableTrustTokenOrigin, SuitableTrustTokenOrigin>&
+            key = entry.first;
+        return matcher.Run(key.first) || matcher.Run(key.second);
+      });
+
+  return deleted_any_data;
+}
+
 }  // namespace network
diff --git a/services/network/trust_tokens/in_memory_trust_token_persister.h b/services/network/trust_tokens/in_memory_trust_token_persister.h
index a279a53a..30203d9 100644
--- a/services/network/trust_tokens/in_memory_trust_token_persister.h
+++ b/services/network/trust_tokens/in_memory_trust_token_persister.h
@@ -9,10 +9,11 @@
 #include <memory>
 #include <utility>
 
+#include "base/callback.h"
 #include "services/network/trust_tokens/proto/public.pb.h"
 #include "services/network/trust_tokens/proto/storage.pb.h"
+#include "services/network/trust_tokens/suitable_trust_token_origin.h"
 #include "services/network/trust_tokens/trust_token_persister.h"
-#include "url/origin.h"
 
 namespace network {
 
@@ -26,29 +27,34 @@
 
   // TrustTokenPersister implementation:
   std::unique_ptr<TrustTokenIssuerConfig> GetIssuerConfig(
-      const url::Origin& issuer) override;
+      const SuitableTrustTokenOrigin& issuer) override;
   std::unique_ptr<TrustTokenToplevelConfig> GetToplevelConfig(
-      const url::Origin& toplevel) override;
+      const SuitableTrustTokenOrigin& toplevel) override;
   std::unique_ptr<TrustTokenIssuerToplevelPairConfig>
-  GetIssuerToplevelPairConfig(const url::Origin& issuer,
-                              const url::Origin& toplevel) override;
+  GetIssuerToplevelPairConfig(
+      const SuitableTrustTokenOrigin& issuer,
+      const SuitableTrustTokenOrigin& toplevel) override;
 
-  void SetIssuerConfig(const url::Origin& issuer,
+  void SetIssuerConfig(const SuitableTrustTokenOrigin& issuer,
                        std::unique_ptr<TrustTokenIssuerConfig> config) override;
   void SetToplevelConfig(
-      const url::Origin& toplevel,
+      const SuitableTrustTokenOrigin& toplevel,
       std::unique_ptr<TrustTokenToplevelConfig> config) override;
   void SetIssuerToplevelPairConfig(
-      const url::Origin& issuer,
-      const url::Origin& toplevel,
+      const SuitableTrustTokenOrigin& issuer,
+      const SuitableTrustTokenOrigin& toplevel,
       std::unique_ptr<TrustTokenIssuerToplevelPairConfig> config) override;
 
+  bool DeleteForOrigins(
+      base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)> matcher)
+      override;
+
  private:
-  std::map<url::Origin, std::unique_ptr<TrustTokenToplevelConfig>>
+  std::map<SuitableTrustTokenOrigin, std::unique_ptr<TrustTokenToplevelConfig>>
       toplevel_configs_;
-  std::map<url::Origin, std::unique_ptr<TrustTokenIssuerConfig>>
+  std::map<SuitableTrustTokenOrigin, std::unique_ptr<TrustTokenIssuerConfig>>
       issuer_configs_;
-  std::map<std::pair<url::Origin, url::Origin>,
+  std::map<std::pair<SuitableTrustTokenOrigin, SuitableTrustTokenOrigin>,
            std::unique_ptr<TrustTokenIssuerToplevelPairConfig>>
       issuer_toplevel_pair_configs_;
 };
diff --git a/services/network/trust_tokens/sqlite_trust_token_persister.cc b/services/network/trust_tokens/sqlite_trust_token_persister.cc
index f22b050..8fb3c7f 100644
--- a/services/network/trust_tokens/sqlite_trust_token_persister.cc
+++ b/services/network/trust_tokens/sqlite_trust_token_persister.cc
@@ -3,10 +3,12 @@
 // found in the LICENSE file.
 
 #include "services/network/trust_tokens/sqlite_trust_token_persister.h"
+
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/sequenced_task_runner.h"
+#include "base/strings/string_split.h"
 #include "components/sqlite_proto/key_value_data.h"
 #include "services/network/trust_tokens/proto/storage.pb.h"
 #include "services/network/trust_tokens/trust_token_database_owner.h"
@@ -16,14 +18,43 @@
 namespace network {
 
 namespace {
-std::string ToKey(const url::Origin& issuer, const url::Origin& toplevel) {
-  DCHECK(issuer.GetURL().SchemeIsHTTPOrHTTPS());
-  DCHECK(toplevel.GetURL().SchemeIsHTTPOrHTTPS());
 
+const char kIssuerToplevelKeySeparator[] = " ";
+
+// Converts an (issuer, top-level origin) pair keying Trust Tokens state into a
+// unique string suitable for indexing persistent storage. Changes should be
+// kept in sync with |FromKey|.
+std::string ToKey(const SuitableTrustTokenOrigin& issuer,
+                  const SuitableTrustTokenOrigin& toplevel) {
   // U+0020 space is a character forbidden in schemes/hosts/ports, so it
   // shouldn't appear in the serialization of either origin, preventing
   // collisions.
-  return issuer.Serialize() + " " + toplevel.Serialize();
+  return issuer.Serialize() + kIssuerToplevelKeySeparator +
+         toplevel.Serialize();
+}
+
+// Attempts to deserialize |key_from_database| fresh off the disk. This might
+// not be the output of |ToKey| because of corruption during storage on disk:
+// returns false on failure.
+//
+// The parameters |issuer| and |toplevel| are pointers-to-optionals because
+// SuitableTrustTokenOrigin does not have a default constructor.
+bool FromKey(base::StringPiece key_from_database,
+             base::Optional<SuitableTrustTokenOrigin>* issuer,
+             base::Optional<SuitableTrustTokenOrigin>* toplevel) {
+  DCHECK(issuer);
+  DCHECK(toplevel);
+
+  auto pieces =
+      base::SplitStringPiece(key_from_database, kIssuerToplevelKeySeparator,
+                             base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+
+  if (pieces.size() != 2)
+    return false;
+
+  *issuer = SuitableTrustTokenOrigin::Create(GURL(pieces[0]));
+  *toplevel = SuitableTrustTokenOrigin::Create(GURL(pieces[1]));
+  return issuer->has_value() && toplevel->has_value();
 }
 
 void OnDatabaseOwnerCreated(
@@ -35,6 +66,68 @@
   std::move(on_done_initializing).Run(std::move(ret));
 }
 
+template <typename T>
+bool DeleteOriginKeyedKeyValueData(
+    base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)> matcher,
+    sqlite_proto::KeyValueData<T>* key_value_data) {
+  DCHECK(key_value_data);
+
+  std::vector<std::string> keys_to_delete;
+  bool data_from_filter_was_deleted = false;
+
+  for (const auto& kv : key_value_data->GetAllCached()) {
+    // Creation can fail if the record was corrupted on disk.
+    base::Optional<SuitableTrustTokenOrigin> maybe_key =
+        SuitableTrustTokenOrigin::Create(GURL(kv.first));
+
+    // If the record's key is corrupt, delete the record no matter what, but
+    // don't record the deletion request as having led to data being deleted.
+    if (!maybe_key) {
+      keys_to_delete.push_back(kv.first);
+      continue;
+    }
+
+    if (matcher.Run(*maybe_key)) {
+      keys_to_delete.push_back(kv.first);
+      data_from_filter_was_deleted = true;
+    }
+  }
+
+  key_value_data->DeleteData(keys_to_delete);
+
+  return data_from_filter_was_deleted;
+}
+
+bool DeleteMatchingIssuerToplevelPairData(
+    base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)> matcher,
+    sqlite_proto::KeyValueData<TrustTokenIssuerToplevelPairConfig>*
+        key_value_data) {
+  std::vector<std::string> keys_to_delete;
+
+  bool data_from_filter_was_deleted = false;
+
+  for (const auto& kv : key_value_data->GetAllCached()) {
+    base::Optional<SuitableTrustTokenOrigin> maybe_issuer;
+    base::Optional<SuitableTrustTokenOrigin> maybe_toplevel;
+
+    // If the record's key is corrupt, delete the record no matter what, but
+    // don't record the deletion request as having led to data being deleted.
+    if (!FromKey(kv.first, &maybe_issuer, &maybe_toplevel)) {
+      keys_to_delete.push_back(kv.first);
+      continue;
+    }
+
+    if (matcher.Run(*maybe_issuer) || matcher.Run(*maybe_toplevel)) {
+      keys_to_delete.push_back(kv.first);
+      data_from_filter_was_deleted = true;
+    }
+  }
+
+  key_value_data->DeleteData(keys_to_delete);
+
+  return data_from_filter_was_deleted;
+}
+
 }  // namespace
 
 SQLiteTrustTokenPersister::SQLiteTrustTokenPersister(
@@ -60,9 +153,8 @@
 }
 
 std::unique_ptr<TrustTokenIssuerConfig>
-SQLiteTrustTokenPersister::GetIssuerConfig(const url::Origin& issuer) {
-  DCHECK(issuer.GetURL().SchemeIsHTTPOrHTTPS());
-
+SQLiteTrustTokenPersister::GetIssuerConfig(
+    const SuitableTrustTokenOrigin& issuer) {
   auto* data = database_owner_->IssuerData();
   CHECK(data);
 
@@ -72,9 +164,8 @@
 }
 
 std::unique_ptr<TrustTokenToplevelConfig>
-SQLiteTrustTokenPersister::GetToplevelConfig(const url::Origin& toplevel) {
-  DCHECK(toplevel.GetURL().SchemeIsHTTPOrHTTPS());
-
+SQLiteTrustTokenPersister::GetToplevelConfig(
+    const SuitableTrustTokenOrigin& toplevel) {
   auto* data = database_owner_->ToplevelData();
   CHECK(data);
 
@@ -85,11 +176,8 @@
 
 std::unique_ptr<TrustTokenIssuerToplevelPairConfig>
 SQLiteTrustTokenPersister::GetIssuerToplevelPairConfig(
-    const url::Origin& issuer,
-    const url::Origin& toplevel) {
-  DCHECK(issuer.GetURL().SchemeIsHTTPOrHTTPS());
-  DCHECK(toplevel.GetURL().SchemeIsHTTPOrHTTPS());
-
+    const SuitableTrustTokenOrigin& issuer,
+    const SuitableTrustTokenOrigin& toplevel) {
   auto* data = database_owner_->IssuerToplevelPairData();
   CHECK(data);
 
@@ -99,10 +187,8 @@
 }
 
 void SQLiteTrustTokenPersister::SetIssuerConfig(
-    const url::Origin& issuer,
+    const SuitableTrustTokenOrigin& issuer,
     std::unique_ptr<TrustTokenIssuerConfig> config) {
-  DCHECK(issuer.GetURL().SchemeIsHTTPOrHTTPS());
-
   sqlite_proto::KeyValueData<TrustTokenIssuerConfig>* data =
       database_owner_->IssuerData();
   CHECK(data);
@@ -110,10 +196,8 @@
 }
 
 void SQLiteTrustTokenPersister::SetToplevelConfig(
-    const url::Origin& toplevel,
+    const SuitableTrustTokenOrigin& toplevel,
     std::unique_ptr<TrustTokenToplevelConfig> config) {
-  DCHECK(toplevel.GetURL().SchemeIsHTTPOrHTTPS());
-
   sqlite_proto::KeyValueData<TrustTokenToplevelConfig>* data =
       database_owner_->ToplevelData();
   CHECK(data);
@@ -121,16 +205,29 @@
 }
 
 void SQLiteTrustTokenPersister::SetIssuerToplevelPairConfig(
-    const url::Origin& issuer,
-    const url::Origin& toplevel,
+    const SuitableTrustTokenOrigin& issuer,
+    const SuitableTrustTokenOrigin& toplevel,
     std::unique_ptr<TrustTokenIssuerToplevelPairConfig> config) {
-  DCHECK(issuer.GetURL().SchemeIsHTTPOrHTTPS());
-  DCHECK(toplevel.GetURL().SchemeIsHTTPOrHTTPS());
-
   sqlite_proto::KeyValueData<TrustTokenIssuerToplevelPairConfig>* data =
       database_owner_->IssuerToplevelPairData();
   CHECK(data);
+
   data->UpdateData(ToKey(issuer, toplevel), *config);
 }
 
+bool SQLiteTrustTokenPersister::DeleteForOrigins(
+    base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)> matcher) {
+  bool any_data_was_deleted = false;
+  any_data_was_deleted |=
+      DeleteOriginKeyedKeyValueData(matcher, database_owner_->IssuerData());
+
+  any_data_was_deleted |=
+      DeleteOriginKeyedKeyValueData(matcher, database_owner_->ToplevelData());
+
+  any_data_was_deleted |= DeleteMatchingIssuerToplevelPairData(
+      matcher, database_owner_->IssuerToplevelPairData());
+
+  return any_data_was_deleted;
+}
+
 }  // namespace network
diff --git a/services/network/trust_tokens/sqlite_trust_token_persister.h b/services/network/trust_tokens/sqlite_trust_token_persister.h
index 7a852eb0..04f18b8 100644
--- a/services/network/trust_tokens/sqlite_trust_token_persister.h
+++ b/services/network/trust_tokens/sqlite_trust_token_persister.h
@@ -11,6 +11,7 @@
 #include "base/task/task_traits.h"
 #include "components/sqlite_proto/key_value_data.h"
 #include "services/network/trust_tokens/proto/storage.pb.h"
+#include "services/network/trust_tokens/suitable_trust_token_origin.h"
 #include "services/network/trust_tokens/trust_token_database_owner.h"
 #include "services/network/trust_tokens/trust_token_persister.h"
 #include "sql/database.h"
@@ -57,30 +58,30 @@
 
   // TrustTokenPersister implementation:
 
-  // Preconditions:
-  // - All of these methods require that ther Origin inputs' schemes must be
-  // HTTP or HTTPS.
-  //
-  // Postconditions:
-  // - Each getter returns nullptr when the requested record was not found.
+  // Each getter returns nullptr when the requested record was not found.
   std::unique_ptr<TrustTokenIssuerConfig> GetIssuerConfig(
-      const url::Origin& issuer) override;
+      const SuitableTrustTokenOrigin& issuer) override;
   std::unique_ptr<TrustTokenToplevelConfig> GetToplevelConfig(
-      const url::Origin& toplevel) override;
+      const SuitableTrustTokenOrigin& toplevel) override;
   std::unique_ptr<TrustTokenIssuerToplevelPairConfig>
-  GetIssuerToplevelPairConfig(const url::Origin& issuer,
-                              const url::Origin& toplevel) override;
+  GetIssuerToplevelPairConfig(
+      const SuitableTrustTokenOrigin& issuer,
+      const SuitableTrustTokenOrigin& toplevel) override;
 
-  void SetIssuerConfig(const url::Origin& issuer,
+  void SetIssuerConfig(const SuitableTrustTokenOrigin& issuer,
                        std::unique_ptr<TrustTokenIssuerConfig> config) override;
   void SetToplevelConfig(
-      const url::Origin& toplevel,
+      const SuitableTrustTokenOrigin& toplevel,
       std::unique_ptr<TrustTokenToplevelConfig> config) override;
   void SetIssuerToplevelPairConfig(
-      const url::Origin& issuer,
-      const url::Origin& toplevel,
+      const SuitableTrustTokenOrigin& issuer,
+      const SuitableTrustTokenOrigin& toplevel,
       std::unique_ptr<TrustTokenIssuerToplevelPairConfig> config) override;
 
+  bool DeleteForOrigins(
+      base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)> matcher)
+      override;
+
  private:
   // Manages the underlying database.
   std::unique_ptr<TrustTokenDatabaseOwner> database_owner_;
diff --git a/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc b/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc
index 7a18971a..a441635 100644
--- a/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc
+++ b/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc
@@ -37,7 +37,7 @@
                        base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
   ASSERT_TRUE(temp_file.IsValid());
 
-  auto origin = url::Origin::Create(GURL("https://a.com/"));
+  auto origin = *SuitableTrustTokenOrigin::Create(GURL("https://a.com/"));
   {
     std::unique_ptr<SQLiteTrustTokenPersister> persister;
     SQLiteTrustTokenPersister::CreateForFilePath(
diff --git a/services/network/trust_tokens/trust_token_persister.h b/services/network/trust_tokens/trust_token_persister.h
index 9d9dea956..63256a72 100644
--- a/services/network/trust_tokens/trust_token_persister.h
+++ b/services/network/trust_tokens/trust_token_persister.h
@@ -7,7 +7,7 @@
 
 #include <memory>
 
-#include "url/origin.h"
+#include "services/network/trust_tokens/suitable_trust_token_origin.h"
 
 namespace network {
 
@@ -28,23 +28,29 @@
   TrustTokenPersister& operator=(const TrustTokenPersister&) = delete;
 
   virtual std::unique_ptr<TrustTokenIssuerConfig> GetIssuerConfig(
-      const url::Origin& issuer) = 0;
+      const SuitableTrustTokenOrigin& issuer) = 0;
   virtual std::unique_ptr<TrustTokenToplevelConfig> GetToplevelConfig(
-      const url::Origin& toplevel) = 0;
+      const SuitableTrustTokenOrigin& toplevel) = 0;
   virtual std::unique_ptr<TrustTokenIssuerToplevelPairConfig>
-  GetIssuerToplevelPairConfig(const url::Origin& issuer,
-                              const url::Origin& toplevel) = 0;
+  GetIssuerToplevelPairConfig(const SuitableTrustTokenOrigin& issuer,
+                              const SuitableTrustTokenOrigin& toplevel) = 0;
 
   virtual void SetIssuerConfig(
-      const url::Origin& issuer,
+      const SuitableTrustTokenOrigin& issuer,
       std::unique_ptr<TrustTokenIssuerConfig> config) = 0;
   virtual void SetToplevelConfig(
-      const url::Origin& toplevel,
+      const SuitableTrustTokenOrigin& toplevel,
       std::unique_ptr<TrustTokenToplevelConfig> config) = 0;
   virtual void SetIssuerToplevelPairConfig(
-      const url::Origin& issuer,
-      const url::Origin& toplevel,
+      const SuitableTrustTokenOrigin& issuer,
+      const SuitableTrustTokenOrigin& toplevel,
       std::unique_ptr<TrustTokenIssuerToplevelPairConfig> config) = 0;
+
+  // Deletes any data stored keyed by matching origins (as issuers or top-level
+  // origins).
+  virtual bool DeleteForOrigins(
+      base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)>
+          matcher) = 0;
 };
 
 }  // namespace network
diff --git a/services/network/trust_tokens/trust_token_persister_unittest.cc b/services/network/trust_tokens/trust_token_persister_unittest.cc
index b251919d..a082bd6e 100644
--- a/services/network/trust_tokens/trust_token_persister_unittest.cc
+++ b/services/network/trust_tokens/trust_token_persister_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "services/network/trust_tokens/trust_token_persister.h"
 
+#include <memory>
 #include <string>
 #include <utility>
 
@@ -46,6 +47,8 @@
  public:
   static std::unique_ptr<TrustTokenPersister> Create() {
     std::unique_ptr<TrustTokenDatabaseOwner> owner;
+    // Fail to open the database, in order to test that the in-memory fallback
+    // on database error works as intended.
     TrustTokenDatabaseOwner::Create(
         /*db_opener=*/base::BindOnce([](sql::Database*) { return false; }),
         base::ThreadTaskRunnerHandle::Get(),
@@ -90,7 +93,24 @@
                          NoDatabaseSqliteTrustTokenPersisterFactory,
                          EndToEndSqliteTrustTokenPersisterFactory>
     TrustTokenPersisterFactoryTypes;
-TYPED_TEST_SUITE(TrustTokenPersisterTest, TrustTokenPersisterFactoryTypes);
+class PersisterFactoryTypeNames {
+ public:
+  template <typename T>
+  static std::string GetName(int) {
+    if (std::is_same<T, InMemoryTrustTokenPersisterFactory>())
+      return "InMemoryPersister";
+    if (std::is_same<T, NoDatabaseSqliteTrustTokenPersisterFactory>())
+      return "SQLitePersisterMemoryFallback";
+    if (std::is_same<T, EndToEndSqliteTrustTokenPersisterFactory>())
+      return "SQLitePersisterOnDisk";
+    NOTREACHED();
+    return "";
+  }
+};
+
+TYPED_TEST_SUITE(TrustTokenPersisterTest,
+                 TrustTokenPersisterFactoryTypes,
+                 PersisterFactoryTypeNames);
 
 TYPED_TEST(TrustTokenPersisterTest, NegativeResults) {
   base::test::TaskEnvironment env;
@@ -98,7 +118,7 @@
   env.RunUntilIdle();  // Give implementations with asynchronous initialization
                        // time to initialize.
 
-  auto origin = url::Origin::Create(GURL("https://a.com/"));
+  auto origin = *SuitableTrustTokenOrigin::Create(GURL("https://a.com/"));
   EXPECT_THAT(persister->GetIssuerConfig(origin), IsNull());
   EXPECT_THAT(persister->GetToplevelConfig(origin), IsNull());
   EXPECT_THAT(persister->GetIssuerToplevelPairConfig(origin, origin), IsNull());
@@ -122,7 +142,7 @@
   *config.add_tokens() = my_token;
 
   auto config_to_store = std::make_unique<TrustTokenIssuerConfig>(config);
-  auto origin = url::Origin::Create(GURL("https://a.com/"));
+  auto origin = *SuitableTrustTokenOrigin::Create(GURL("https://a.com/"));
   persister->SetIssuerConfig(origin, std::move(config_to_store));
 
   env.RunUntilIdle();  // Give implementations with asynchronous write
@@ -149,7 +169,7 @@
   *config.add_associated_issuers() = "an issuer";
 
   auto config_to_store = std::make_unique<TrustTokenToplevelConfig>(config);
-  auto origin = url::Origin::Create(GURL("https://a.com/"));
+  auto origin = *SuitableTrustTokenOrigin::Create(GURL("https://a.com/"));
   persister->SetToplevelConfig(origin, std::move(config_to_store));
   env.RunUntilIdle();  // Give implementations with asynchronous write
                        // operations time to complete the operation.
@@ -176,8 +196,8 @@
 
   auto config_to_store =
       std::make_unique<TrustTokenIssuerToplevelPairConfig>(config);
-  auto toplevel = url::Origin::Create(GURL("https://a.com/"));
-  auto issuer = url::Origin::Create(GURL("https://issuer.com/"));
+  auto toplevel = *SuitableTrustTokenOrigin::Create(GURL("https://a.com/"));
+  auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
   persister->SetIssuerToplevelPairConfig(issuer, toplevel,
                                          std::move(config_to_store));
   env.RunUntilIdle();  // Give implementations with asynchronous write
@@ -194,4 +214,133 @@
   env.RunUntilIdle();
 }
 
+TYPED_TEST(TrustTokenPersisterTest, DeletesIssuerToplevelKeyedData) {
+  base::test::TaskEnvironment env;
+  std::unique_ptr<TrustTokenPersister> persister = TypeParam::Create();
+  env.RunUntilIdle();  // Give implementations with asynchronous initialization
+                       // time to initialize.
+
+  TrustTokenIssuerToplevelPairConfig pair_config;
+  pair_config.set_last_redemption("five o'clock");
+
+  auto toplevel = *SuitableTrustTokenOrigin::Create(GURL("https://a.com/"));
+  auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
+  persister->SetIssuerToplevelPairConfig(
+      issuer, toplevel,
+      std::make_unique<TrustTokenIssuerToplevelPairConfig>(pair_config));
+  env.RunUntilIdle();  // Give implementations with asynchronous write
+                       // operations time to complete the operation.
+
+  // A matcher matching neither the issuer nor the top-level origin should not
+  // delete (issuer, top level)-keyed data.
+  EXPECT_FALSE(persister->DeleteForOrigins(base::BindLambdaForTesting(
+      [&](const SuitableTrustTokenOrigin& origin) { return false; })));
+
+  // A matcher matching the issuer should delete (issuer, top level)-keyed data.
+  EXPECT_TRUE(persister->DeleteForOrigins(
+      base::BindLambdaForTesting([&](const SuitableTrustTokenOrigin& origin) {
+        return origin == issuer;
+      })));
+  env.RunUntilIdle();  // Give implementations with asynchronous write
+                       // operations time to complete the operation.
+  EXPECT_FALSE(persister->GetIssuerToplevelPairConfig(issuer, toplevel));
+
+  // A matcher matching the top-level origin should delete (issuer, top
+  // level)-keyed data, too.
+  persister->SetIssuerToplevelPairConfig(
+      issuer, toplevel,
+      std::make_unique<TrustTokenIssuerToplevelPairConfig>(pair_config));
+
+  env.RunUntilIdle();  // Give implementations with asynchronous write
+                       // operations time to complete the operation.
+  ASSERT_TRUE(persister->GetIssuerToplevelPairConfig(issuer, toplevel));
+
+  EXPECT_TRUE(persister->DeleteForOrigins(
+      base::BindLambdaForTesting([&](const SuitableTrustTokenOrigin& origin) {
+        return origin == toplevel;
+      })));
+  env.RunUntilIdle();  // Give implementations with asynchronous write
+                       // operations time to complete the operation.
+  EXPECT_FALSE(persister->GetIssuerToplevelPairConfig(issuer, toplevel));
+
+  // Some implementations of TrustTokenPersister may release resources
+  // asynchronously at destruction time; manually free the persister and allow
+  // this asynchronous release to occur, if any.
+  persister.reset();
+  env.RunUntilIdle();
+}
+
+TYPED_TEST(TrustTokenPersisterTest, DeletesIssuerKeyedData) {
+  base::test::TaskEnvironment env;
+  std::unique_ptr<TrustTokenPersister> persister = TypeParam::Create();
+  env.RunUntilIdle();  // Give implementations with asynchronous initialization
+                       // time to initialize.
+
+  TrustTokenIssuerConfig issuer_config;
+  issuer_config.add_tokens()->set_signing_key("key");
+
+  auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com/"));
+
+  persister->SetIssuerConfig(
+      issuer, std::make_unique<TrustTokenIssuerConfig>(issuer_config));
+  env.RunUntilIdle();  // Give implementations with asynchronous write
+                       // operations time to complete the operation.
+  ASSERT_TRUE(persister->GetIssuerConfig(issuer));
+
+  // Deleting with a matcher not matching |issuer| should no-op.
+  EXPECT_FALSE(persister->DeleteForOrigins(base::BindLambdaForTesting(
+      [&](const SuitableTrustTokenOrigin& origin) { return false; })));
+
+  // Deleting with a matcher not matching |issuer| should delete data.
+  EXPECT_TRUE(persister->DeleteForOrigins(
+      base::BindLambdaForTesting([&](const SuitableTrustTokenOrigin& origin) {
+        return origin == issuer;
+      })));
+  env.RunUntilIdle();  // Give implementations with asynchronous write
+                       // operations time to complete the operation.
+  ASSERT_FALSE(persister->GetIssuerConfig(issuer));
+
+  // Some implementations of TrustTokenPersister may release resources
+  // asynchronously at destruction time; manually free the persister and allow
+  // this asynchronous release to occur, if any.
+  persister.reset();
+  env.RunUntilIdle();
+}
+
+TYPED_TEST(TrustTokenPersisterTest, DeletesToplevelKeyedData) {
+  base::test::TaskEnvironment env;
+  std::unique_ptr<TrustTokenPersister> persister = TypeParam::Create();
+  env.RunUntilIdle();  // Give implementations with asynchronous initialization
+                       // time to initialize.
+
+  TrustTokenToplevelConfig toplevel_config;
+  *toplevel_config.add_associated_issuers() = "some issuer";
+
+  auto toplevel = *SuitableTrustTokenOrigin::Create(GURL("https://a.com/"));
+  persister->SetToplevelConfig(
+      toplevel, std::make_unique<TrustTokenToplevelConfig>(toplevel_config));
+  env.RunUntilIdle();  // Give implementations with asynchronous write
+                       // operations time to complete the operation.
+  ASSERT_TRUE(persister->GetToplevelConfig(toplevel));
+
+  // Deleting with a matcher not matching |toplevel| should no-op.
+  EXPECT_FALSE(persister->DeleteForOrigins(base::BindLambdaForTesting(
+      [&](const SuitableTrustTokenOrigin& origin) { return false; })));
+
+  // Deleting with a matcher matching |toplevel| should delete the data.
+  EXPECT_TRUE(persister->DeleteForOrigins(
+      base::BindLambdaForTesting([&](const SuitableTrustTokenOrigin& origin) {
+        return origin == toplevel;
+      })));
+  env.RunUntilIdle();  // Give implementations with asynchronous write
+                       // operations time to complete the operation.
+  ASSERT_FALSE(persister->GetToplevelConfig(toplevel));
+
+  // Some implementations of TrustTokenPersister may release resources
+  // asynchronously at destruction time; manually free the persister and allow
+  // this asynchronous release to occur, if any.
+  persister.reset();
+  env.RunUntilIdle();
+}
+
 }  // namespace network
diff --git a/services/network/trust_tokens/trust_token_request_signing_helper.cc b/services/network/trust_tokens/trust_token_request_signing_helper.cc
index fa467275..15cfdce6e 100644
--- a/services/network/trust_tokens/trust_token_request_signing_helper.cc
+++ b/services/network/trust_tokens/trust_token_request_signing_helper.cc
@@ -351,9 +351,9 @@
   signing_data.insert(signing_data.end(), maybe_request_in_cbor->begin(),
                       maybe_request_in_cbor->end());
 
-  signer_->Init(
-      base::as_bytes(base::make_span(redemption_record.signing_key())));
-  return signer_->Sign(base::make_span(signing_data));
+  base::span<const uint8_t> key_bytes =
+      base::as_bytes(base::make_span(redemption_record.signing_key()));
+  return signer_->Sign(key_bytes, base::make_span(signing_data));
 }
 
 }  // namespace network
diff --git a/services/network/trust_tokens/trust_token_request_signing_helper.h b/services/network/trust_tokens/trust_token_request_signing_helper.h
index 463e05869..c18da32c1 100644
--- a/services/network/trust_tokens/trust_token_request_signing_helper.h
+++ b/services/network/trust_tokens/trust_token_request_signing_helper.h
@@ -115,13 +115,9 @@
    public:
     virtual ~Signer() = default;
 
-    // Initializes signer state with the given key. Must be called at least once
-    // before the first call to |Sign|.
-    virtual void Init(base::span<const uint8_t> key) = 0;
-
-    // Returns a one-shot signature over the given data, or an error. |Init|
-    // must have been called before the first call to |Sign|.
+    // Returns a one-shot signature over the given data, or an error.
     virtual base::Optional<std::vector<uint8_t>> Sign(
+        base::span<const uint8_t> key,
         base::span<const uint8_t> data) = 0;
 
     // Verifies the given signature. Does not depend on the current state of the
diff --git a/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc b/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc
index 40567a9..0db8aed3 100644
--- a/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc
+++ b/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc
@@ -54,8 +54,8 @@
 // not verification.
 class FakeSigner : public TrustTokenRequestSigningHelper::Signer {
  public:
-  void Init(base::span<const uint8_t> key) override {}
   base::Optional<std::vector<uint8_t>> Sign(
+      base::span<const uint8_t> key,
       base::span<const uint8_t> data) override {
     return std::vector<uint8_t>{'s', 'i', 'g', 'n', 'e', 'd'};
   }
@@ -73,8 +73,8 @@
 // be signing over.
 class IdentitySigner : public TrustTokenRequestSigningHelper::Signer {
  public:
-  void Init(base::span<const uint8_t> key) override {}
   base::Optional<std::vector<uint8_t>> Sign(
+      base::span<const uint8_t> key,
       base::span<const uint8_t> data) override {
     return std::vector<uint8_t>(data.begin(), data.end());
   }
@@ -88,8 +88,8 @@
 // FailingSigner always fails the Sign and Verify options.
 class FailingSigner : public TrustTokenRequestSigningHelper::Signer {
  public:
-  void Init(base::span<const uint8_t> key) override {}
   base::Optional<std::vector<uint8_t>> Sign(
+      base::span<const uint8_t> key,
       base::span<const uint8_t> data) override {
     return base::nullopt;
   }
diff --git a/services/network/trust_tokens/trust_token_store.cc b/services/network/trust_tokens/trust_token_store.cc
index df449a0..8cbf0cb 100644
--- a/services/network/trust_tokens/trust_token_store.cc
+++ b/services/network/trust_tokens/trust_token_store.cc
@@ -8,6 +8,8 @@
 #include <utility>
 
 #include "base/optional.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
 #include "services/network/public/mojom/trust_tokens.mojom-forward.h"
 #include "services/network/trust_tokens/in_memory_trust_token_persister.h"
 #include "services/network/trust_tokens/proto/public.pb.h"
@@ -15,6 +17,7 @@
 #include "services/network/trust_tokens/trust_token_parameterization.h"
 #include "services/network/trust_tokens/types.h"
 #include "third_party/protobuf/src/google/protobuf/repeated_field.h"
+#include "url/origin.h"
 
 namespace network {
 
@@ -264,4 +267,41 @@
   return config->signed_redemption_record();
 }
 
+bool TrustTokenStore::ClearDataForFilter(mojom::ClearDataFilterPtr filter) {
+  DCHECK(filter);
+
+  // Returns whether |storage_key|'s data should be deleted, based on the logic
+  // |filter| specifies.
+  auto matcher = base::BindRepeating(
+      [](const mojom::ClearDataFilter& filter,
+         const SuitableTrustTokenOrigin& storage_key) -> bool {
+        // Match an origin if
+        // - it is an eTLD+1 (aka "domain and registry") match with anything on
+        // |filter|'s domain list, or
+        // - it is an origin match with anything on |filter|'s origin list.
+        bool is_match = base::Contains(filter.origins, storage_key.origin());
+
+        // Computing the domain might be a little expensive, so
+        // skip it if we know for sure the origin is a match because it
+        // matches the origin list.
+        if (!is_match) {
+          std::string etld1_for_origin =
+              net::registry_controlled_domains::GetDomainAndRegistry(
+                  storage_key.origin().host(),
+                  net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+          is_match = base::Contains(filter.domains, etld1_for_origin);
+        }
+
+        switch (filter.type) {
+          case mojom::ClearDataFilter::Type::KEEP_MATCHES:
+            return !is_match;
+          case mojom::ClearDataFilter::Type::DELETE_MATCHES:
+            return is_match;
+        }
+      },
+      *filter);
+
+  return persister_->DeleteForOrigins(std::move(matcher));
+}
+
 }  // namespace network
diff --git a/services/network/trust_tokens/trust_token_store.h b/services/network/trust_tokens/trust_token_store.h
index b247092..6e8a4b3 100644
--- a/services/network/trust_tokens/trust_token_store.h
+++ b/services/network/trust_tokens/trust_token_store.h
@@ -14,6 +14,7 @@
 #include "base/optional.h"
 #include "base/sequenced_task_runner.h"
 #include "base/time/time.h"
+#include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/public/mojom/trust_tokens.mojom.h"
 #include "services/network/trust_tokens/proto/public.pb.h"
 #include "services/network/trust_tokens/suitable_trust_token_origin.h"
@@ -186,6 +187,23 @@
   RetrieveNonstaleRedemptionRecord(const SuitableTrustTokenOrigin& issuer,
                                    const SuitableTrustTokenOrigin& top_level);
 
+  //// Methods concerning data removal
+
+  // Deletes any data stored keyed by matching origins (as issuers or top-level
+  // origins).
+  //
+  // An origin "matches" |filter| means it compares equal to a member of
+  // |filter->origins| or its domain-and-registry string---aka "eTLD+1"---is an
+  // exact match to a member of |filter->domains|.
+  //
+  // If |filter->type| is KEEP_MATCHING, deletes all data for every origin *not*
+  // matching the filter. (In particular, this will still delete data keyed by
+  // a pair of origins, one of which matches and one of which does not.)
+  //
+  // Returns whether any data was deleted.
+  WARN_UNUSED_RESULT virtual bool ClearDataForFilter(
+      mojom::ClearDataFilterPtr filter);
+
  private:
   std::unique_ptr<TrustTokenPersister> persister_;
   std::unique_ptr<RecordExpiryDelegate> record_expiry_delegate_;
diff --git a/services/network/trust_tokens/trust_token_store_unittest.cc b/services/network/trust_tokens/trust_token_store_unittest.cc
index a4b9eec..245bc31 100644
--- a/services/network/trust_tokens/trust_token_store_unittest.cc
+++ b/services/network/trust_tokens/trust_token_store_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
+#include "services/network/public/mojom/network_context.mojom.h"
 #include "services/network/trust_tokens/in_memory_trust_token_persister.h"
 #include "services/network/trust_tokens/proto/public.pb.h"
 #include "services/network/trust_tokens/proto/storage.pb.h"
@@ -526,5 +527,120 @@
 
 // TODO(crbug.com/1065388) Add a test exercising the maximum batch size.
 
+TEST(TrustTokenStore, EmptyFilter) {
+  // Deletion with an empty filter should no-op.
+
+  auto store = TrustTokenStore::CreateInMemory();
+  auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com"));
+  store->AddTokens(issuer, std::vector<std::string>{"token"}, "key");
+
+  EXPECT_FALSE(store->ClearDataForFilter(mojom::ClearDataFilter::New()));
+  EXPECT_TRUE(store->CountTokens(issuer));
+}
+
+TEST(TrustTokenStore, EmptyFilterInKeepMatchesMode) {
+  auto store = TrustTokenStore::CreateInMemory();
+  auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com"));
+  store->AddTokens(issuer, std::vector<std::string>{"token"}, "key");
+
+  // An empty filter in mode KEEP_MATCHES should act as a wildcard "wipe the
+  // store" clear.
+  auto filter_matching_all_data = mojom::ClearDataFilter::New();
+  filter_matching_all_data->type = mojom::ClearDataFilter::Type::KEEP_MATCHES;
+
+  EXPECT_TRUE(store->ClearDataForFilter(std::move(filter_matching_all_data)));
+  EXPECT_FALSE(store->CountTokens(issuer));
+}
+
+TEST(TrustTokenStore, ClearsIssuerKeyedData) {
+  auto store = TrustTokenStore::CreateInMemory();
+  auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com"));
+
+  store->AddTokens(issuer, std::vector<std::string>{"token"}, "key");
+
+  auto filter = mojom::ClearDataFilter::New();
+  filter->origins.push_back(issuer);
+  EXPECT_TRUE(store->ClearDataForFilter(std::move(filter)));
+  EXPECT_FALSE(store->CountTokens(issuer));
+}
+
+TEST(TrustTokenStore, ClearsToplevelKeyedData) {
+  auto store = TrustTokenStore::CreateInMemory();
+  auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com"));
+  auto toplevel =
+      *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com"));
+
+  // (The list of issuers associated with each top-level origin is keyed solely
+  // by top-level origin because it is configuration set by the top-level
+  // origin.)
+  ASSERT_TRUE(store->SetAssociation(issuer, toplevel));
+  auto filter = mojom::ClearDataFilter::New();
+  filter->origins.push_back(toplevel);
+  EXPECT_TRUE(store->ClearDataForFilter(std::move(filter)));
+  EXPECT_FALSE(store->IsAssociated(issuer, toplevel));
+}
+
+TEST(TrustTokenStore, ClearsIssuerToplevelPairKeyedData) {
+  auto store = TrustTokenStore::CreateInMemory();
+  auto issuer = *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com"));
+  auto toplevel =
+      *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com"));
+
+  {
+    store->SetRedemptionRecord(issuer, toplevel,
+                               SignedTrustTokenRedemptionRecord());
+    auto filter = mojom::ClearDataFilter::New();
+    filter->origins.push_back(issuer);
+    EXPECT_TRUE(store->ClearDataForFilter(std::move(filter)));
+    EXPECT_FALSE(store->RetrieveNonstaleRedemptionRecord(issuer, toplevel));
+  }
+
+  {
+    store->SetRedemptionRecord(issuer, toplevel,
+                               SignedTrustTokenRedemptionRecord());
+    auto filter = mojom::ClearDataFilter::New();
+    filter->origins.push_back(toplevel);
+    EXPECT_TRUE(store->ClearDataForFilter(std::move(filter)));
+    EXPECT_FALSE(store->RetrieveNonstaleRedemptionRecord(issuer, toplevel));
+  }
+}
+
+TEST(TrustTokenStore, ClearDataCanFilterByDomain) {
+  auto store = TrustTokenStore::CreateInMemory();
+  auto issuer = *SuitableTrustTokenOrigin::Create(
+      GURL("https://arbitrary.https.subdomain.of.issuer.com"));
+
+  store->AddTokens(issuer, std::vector<std::string>{"token"}, "key");
+
+  auto filter = mojom::ClearDataFilter::New();
+  filter->domains.push_back("issuer.com");
+  EXPECT_TRUE(store->ClearDataForFilter(std::move(filter)));
+  EXPECT_FALSE(store->CountTokens(issuer));
+}
+
+TEST(TrustTokenStore, RemovesDataForInvertedFilters) {
+  auto store = TrustTokenStore::CreateInMemory();
+  auto issuer =
+      *SuitableTrustTokenOrigin::Create(GURL("https://www.issuer.com"));
+  auto toplevel =
+      *SuitableTrustTokenOrigin::Create(GURL("https://www.toplevel.com"));
+
+  store->AddTokens(issuer, std::vector<std::string>{"token"}, "key");
+  store->SetRedemptionRecord(issuer, toplevel,
+                             SignedTrustTokenRedemptionRecord{});
+
+  // With a "delete all origins not covered by this filter"-type filter
+  // containing just the issuer, the issuer's data shouldn't be touched, but the
+  // (issuer, toplevel)-keyed data should be cleared as one origin (the
+  // non-matching one) qualifies for deletion.
+  auto filter = mojom::ClearDataFilter::New();
+  filter->type = mojom::ClearDataFilter::Type::KEEP_MATCHES;
+  filter->origins.push_back(issuer);
+
+  EXPECT_TRUE(store->ClearDataForFilter(std::move(filter)));
+  EXPECT_TRUE(store->CountTokens(issuer));
+  EXPECT_FALSE(store->RetrieveNonstaleRedemptionRecord(issuer, toplevel));
+}
+
 }  // namespace trust_tokens
 }  // namespace network
diff --git a/testing/buildbot/chromium.ci.json b/testing/buildbot/chromium.ci.json
index f8c7aa4..e9d05c8 100644
--- a/testing/buildbot/chromium.ci.json
+++ b/testing/buildbot/chromium.ci.json
@@ -23693,6 +23693,631 @@
   "Fuchsia ARM64": {
     "additional_compile_targets": [
       "all"
+    ],
+    "gtest_tests": [
+      {
+        "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": "angle_unittests",
+        "test_target": "//third_party/angle/src/tests:angle_unittests"
+      },
+      {
+        "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": "base_unittests",
+        "test_target": "//base:base_unittests"
+      },
+      {
+        "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": "base_util_unittests",
+        "test_target": "//base/util:base_util_unittests"
+      },
+      {
+        "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": "blink_common_unittests",
+        "test_target": "//third_party/blink/common:blink_common_unittests"
+      },
+      {
+        "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": "blink_heap_unittests",
+        "test_target": "//third_party/blink/renderer/platform/heap:blink_heap_unittests"
+      },
+      {
+        "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": "blink_platform_unittests",
+        "test_target": "//third_party/blink/renderer/platform:blink_platform_unittests"
+      },
+      {
+        "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": "cast_runner_browsertests",
+        "test_target": "//fuchsia/runners:cast_runner_browsertests"
+      },
+      {
+        "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": "cast_runner_integration_tests",
+        "test_target": "//fuchsia/runners:cast_runner_integration_tests"
+      },
+      {
+        "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": "cast_runner_unittests",
+        "test_target": "//fuchsia/runners:cast_runner_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter"
+        ],
+        "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": "content_unittests",
+        "test_target": "//content/test:content_unittests"
+      },
+      {
+        "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": "cr_fuchsia_base_unittests",
+        "test_target": "//fuchsia/base:cr_fuchsia_base_unittests"
+      },
+      {
+        "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": "cronet_tests",
+        "test_target": "//components/cronet:cronet_tests"
+      },
+      {
+        "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": "cronet_unittests",
+        "test_target": "//components/cronet:cronet_unittests"
+      },
+      {
+        "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": "crypto_unittests",
+        "test_target": "//crypto:crypto_unittests"
+      },
+      {
+        "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": "events_unittests",
+        "test_target": "//ui/events:events_unittests"
+      },
+      {
+        "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": "gfx_unittests",
+        "test_target": "//ui/gfx:gfx_unittests"
+      },
+      {
+        "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": "gpu_unittests",
+        "test_target": "//gpu:gpu_unittests"
+      },
+      {
+        "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": "http_service_tests",
+        "test_target": "//fuchsia/http:http_service_tests"
+      },
+      {
+        "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": "ipc_tests",
+        "test_target": "//ipc:ipc_tests"
+      },
+      {
+        "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_target": "//media:media_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.mojo_unittests.filter"
+        ],
+        "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": "mojo_unittests",
+        "test_target": "//mojo:mojo_unittests"
+      },
+      {
+        "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": "perfetto_unittests",
+        "test_target": "//third_party/perfetto:perfetto_unittests"
+      },
+      {
+        "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": "service_manager_unittests",
+        "test_target": "//services/service_manager/tests:service_manager_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.services_unittests.filter"
+        ],
+        "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": "services_unittests",
+        "test_target": "//services:services_unittests"
+      },
+      {
+        "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": "skia_unittests",
+        "test_target": "//skia:skia_unittests"
+      },
+      {
+        "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": "sql_unittests",
+        "test_target": "//sql:sql_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter"
+        ],
+        "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": "ui_base_unittests",
+        "test_target": "//ui/base:ui_base_unittests"
+      },
+      {
+        "args": [
+          "--child-arg=--ozone-platform=headless"
+        ],
+        "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": "viz_unittests",
+        "test_target": "//components/viz:viz_unittests"
+      },
+      {
+        "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": "web_engine_browsertests",
+        "test_target": "//fuchsia/engine:web_engine_browsertests"
+      },
+      {
+        "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": "web_engine_integration_tests",
+        "test_target": "//fuchsia/engine:web_engine_integration_tests"
+      },
+      {
+        "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": "web_engine_unittests",
+        "test_target": "//fuchsia/engine:web_engine_unittests"
+      },
+      {
+        "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": "web_runner_integration_tests",
+        "test_target": "//fuchsia/runners:web_runner_integration_tests"
+      }
     ]
   },
   "Fuchsia x64": {
@@ -90253,6 +90878,53 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "name": "site_per_process_android_browsertests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "android_browsertests",
+        "test_target": "//chrome/test:android_browsertests"
+      },
+      {
+        "args": [
+          "--site-per-process"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "site_per_process_chrome_public_test_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 20
+        },
+        "test": "chrome_public_test_apk",
+        "test_target": "//chrome/android:chrome_public_test_apk"
+      },
+      {
+        "args": [
+          "--site-per-process"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
         "name": "site_per_process_components_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -90325,6 +90997,30 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "name": "site_per_process_content_shell_test_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 3
+        },
+        "test": "content_shell_test_apk",
+        "test_target": "//content/shell/android:content_shell_test_apk"
+      },
+      {
+        "args": [
+          "--site-per-process"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
         "name": "site_per_process_content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -124693,7 +125389,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -124732,7 +125430,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -124771,7 +125471,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -124810,7 +125512,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -124849,7 +125553,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -124888,7 +125594,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -124927,7 +125635,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -124966,7 +125676,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -125005,7 +125717,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -125044,7 +125758,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -125083,7 +125799,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -125122,7 +125840,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -125161,7 +125881,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -125200,7 +125922,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -125239,7 +125963,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -125278,7 +126004,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -125317,7 +126045,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -125375,7 +126105,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -125411,7 +126143,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -125447,7 +126181,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -125483,7 +126219,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -125519,7 +126257,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -125555,7 +126295,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -125591,7 +126333,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -125627,7 +126371,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -125663,7 +126409,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -125699,7 +126447,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -125735,7 +126485,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -125771,7 +126523,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -125807,7 +126561,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -125843,7 +126599,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -125879,7 +126637,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -125915,7 +126675,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -125951,7 +126713,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -196572,7 +197336,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -196611,7 +197377,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -196650,7 +197418,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -196689,7 +197459,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -196728,7 +197500,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -196767,7 +197541,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -196806,7 +197582,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -196845,7 +197623,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -196884,7 +197664,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -196923,7 +197705,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -196962,7 +197746,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -197001,7 +197787,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -197040,7 +197828,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -197079,7 +197869,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -197118,7 +197910,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -197157,7 +197951,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -197196,7 +197992,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -197235,7 +198033,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -197274,7 +198074,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -197313,7 +198115,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -197352,7 +198156,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -197392,7 +198198,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -197432,7 +198240,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -197471,7 +198281,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -197510,7 +198322,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -197550,7 +198364,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -197590,7 +198406,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -197629,7 +198447,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -197668,7 +198488,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -197707,7 +198529,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -197746,7 +198570,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -197785,7 +198611,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -197824,7 +198652,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -197863,7 +198693,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -197902,7 +198734,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -197941,7 +198775,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -197980,7 +198816,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -198019,7 +198857,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -198058,7 +198898,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -198097,7 +198939,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -198136,7 +198980,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -198175,7 +199021,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -198214,7 +199062,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -198253,7 +199103,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -198292,7 +199144,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -198331,7 +199185,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -198370,7 +199226,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -198409,7 +199267,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -198448,7 +199308,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -198487,7 +199349,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -198526,7 +199390,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -198565,7 +199431,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -198604,7 +199472,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -198643,7 +199513,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -198682,7 +199554,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -198721,7 +199595,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -198760,7 +199636,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -198799,7 +199677,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -198838,7 +199718,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -198877,7 +199759,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -198916,7 +199800,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -198955,7 +199841,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -198994,7 +199882,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -199033,7 +199923,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -199072,7 +199964,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -199111,7 +200005,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -199150,7 +200046,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -199189,7 +200087,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -199228,7 +200128,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -199267,7 +200169,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -199306,7 +200210,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -199345,7 +200251,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -199388,7 +200296,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "base_unittests",
@@ -199428,7 +200338,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "boringssl_crypto_tests",
@@ -199468,7 +200380,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "boringssl_ssl_tests",
@@ -199508,7 +200422,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "components_unittests",
@@ -199548,7 +200464,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "crypto_unittests",
@@ -199588,7 +200506,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "gfx_unittests",
@@ -199628,7 +200548,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "google_apis_unittests",
@@ -199668,7 +200590,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
@@ -199708,7 +200632,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_integration_eg2tests_module",
@@ -199749,7 +200675,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_settings_eg2tests_module",
@@ -199789,7 +200717,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_signin_eg2tests_module",
@@ -199829,7 +200759,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
@@ -199869,7 +200801,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_ui_eg2tests_module",
@@ -199910,7 +200844,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_unittests",
@@ -199950,7 +200886,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_web_eg2tests_module",
@@ -199990,7 +200928,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_components_unittests",
@@ -200030,7 +200970,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_net_unittests",
@@ -200070,7 +201012,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_remoting_unittests",
@@ -200110,7 +201054,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_showcase_eg2tests_module",
@@ -200150,7 +201096,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_testing_unittests",
@@ -200190,7 +201138,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_web_inttests",
@@ -200230,7 +201180,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_web_shell_eg2tests_module",
@@ -200270,7 +201222,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_web_unittests",
@@ -200310,7 +201264,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_web_view_inttests",
@@ -200350,7 +201306,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_web_view_unittests",
@@ -200390,7 +201348,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "net_unittests",
@@ -200430,7 +201390,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "services_unittests",
@@ -200470,7 +201432,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "skia_unittests",
@@ -200510,7 +201474,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "sql_unittests",
@@ -200550,7 +201516,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ui_base_unittests",
@@ -200590,7 +201558,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "url_unittests",
@@ -200634,7 +201604,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "cronet_test",
         "merge": {
@@ -200673,7 +201645,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "cronet_test",
         "merge": {
@@ -200719,7 +201693,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -200758,7 +201734,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -200797,7 +201775,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -200836,7 +201816,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -200875,7 +201857,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -200914,7 +201898,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -200954,7 +201940,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -200994,7 +201982,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -201034,7 +202024,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -201073,7 +202065,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -201112,7 +202106,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -201151,7 +202147,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -201190,7 +202188,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -201229,7 +202229,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -201269,7 +202271,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -201309,7 +202313,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -201349,7 +202355,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -201389,7 +202397,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -201429,7 +202439,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -201468,7 +202480,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -201507,7 +202521,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -201546,7 +202562,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -201585,7 +202603,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -201624,7 +202644,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -201663,7 +202685,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -201702,7 +202726,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -201741,7 +202767,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -201781,7 +202809,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -201821,7 +202851,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -201861,7 +202893,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -201900,7 +202934,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -201939,7 +202975,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -201978,7 +203016,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -202017,7 +203057,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -202056,7 +203098,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -202095,7 +203139,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -202134,7 +203180,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -202173,7 +203221,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -202212,7 +203262,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -202251,7 +203303,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -202290,7 +203344,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -202329,7 +203385,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -202374,7 +203432,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -202415,7 +203475,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -202456,7 +203518,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -202497,7 +203561,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -202538,7 +203604,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -202579,7 +203647,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -202620,7 +203690,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -202661,7 +203733,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -202702,7 +203776,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -202743,7 +203819,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -202784,7 +203862,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -202825,7 +203905,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -202866,7 +203948,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -202907,7 +203991,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -202948,7 +204034,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -202989,7 +204077,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -203030,7 +204120,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -203072,7 +204164,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -203114,7 +204208,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -203155,7 +204251,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -203196,7 +204294,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -203238,7 +204338,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -203280,7 +204382,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -203321,7 +204425,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -203362,7 +204468,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -203403,7 +204511,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -203444,7 +204554,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -203486,7 +204598,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -203528,7 +204642,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -203569,7 +204685,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -203610,7 +204728,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -203651,7 +204771,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -203692,7 +204814,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -203733,7 +204857,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -203774,7 +204900,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -203815,7 +204943,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -203856,7 +204986,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -203897,7 +205029,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -203938,7 +205072,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -203979,7 +205115,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -204020,7 +205158,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -204061,7 +205201,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -204102,7 +205244,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -204143,7 +205287,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -204184,7 +205330,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -204225,7 +205373,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -204266,7 +205416,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -204307,7 +205459,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -204348,7 +205502,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -204389,7 +205545,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -204430,7 +205588,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -204471,7 +205631,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -204512,7 +205674,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -204553,7 +205717,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -204594,7 +205760,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -204635,7 +205803,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -204676,7 +205846,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -204717,7 +205889,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -204758,7 +205932,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -204799,7 +205975,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -204840,7 +206018,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -204881,7 +206061,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -204922,7 +206104,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -204963,7 +206147,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -205009,7 +206195,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -205048,7 +206236,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -205087,7 +206277,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -205126,7 +206318,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -205165,7 +206359,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -205204,7 +206400,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -205243,7 +206441,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -205282,7 +206482,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -205321,7 +206523,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -205360,7 +206564,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -205399,7 +206605,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -205438,7 +206646,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -205477,7 +206687,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -205516,7 +206728,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -205555,7 +206769,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -205594,7 +206810,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -205633,7 +206851,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -205672,7 +206892,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -205711,7 +206933,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -205750,7 +206974,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -205789,7 +207015,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -205828,7 +207056,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -205867,7 +207097,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -205906,7 +207138,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -205945,7 +207179,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -205984,7 +207220,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -206023,7 +207261,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -206062,7 +207302,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -206101,7 +207343,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -206140,7 +207384,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -206179,7 +207425,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -206218,7 +207466,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -206257,7 +207507,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -206296,7 +207548,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -206335,7 +207589,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -206374,7 +207630,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -206414,7 +207672,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -206454,7 +207714,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -206494,7 +207756,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -206534,7 +207798,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -206574,7 +207840,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -206614,7 +207882,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -206654,7 +207924,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -206694,7 +207966,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -206734,7 +208008,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -206773,7 +208049,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -206812,7 +208090,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -206851,7 +208131,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -206890,7 +208172,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -206929,7 +208213,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -206968,7 +208254,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -207007,7 +208295,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -207046,7 +208336,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -207085,7 +208377,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -207125,7 +208419,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -207165,7 +208461,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -207205,7 +208503,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -207245,7 +208545,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -207284,7 +208586,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -207323,7 +208627,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -207362,7 +208668,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -207401,7 +208709,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -207440,7 +208750,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -207479,7 +208791,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -207518,7 +208832,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -207557,7 +208873,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -207596,7 +208914,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -207635,7 +208955,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -207674,7 +208996,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -207713,7 +209037,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -207752,7 +209078,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -207791,7 +209119,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -207830,7 +209160,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -207869,7 +209201,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -207908,7 +209242,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -207947,7 +209283,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -207987,7 +209325,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -208027,7 +209367,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -208067,7 +209409,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -208107,7 +209451,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -208147,7 +209493,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -208187,7 +209535,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -208227,7 +209577,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -208267,7 +209619,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -208307,7 +209661,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -208346,7 +209702,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -208385,7 +209743,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -208424,7 +209784,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -208463,7 +209825,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -208502,7 +209866,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -208541,7 +209907,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -208580,7 +209948,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -208619,7 +209989,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -208658,7 +210030,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -208697,7 +210071,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -208736,7 +210112,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -208775,7 +210153,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -208814,7 +210194,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -208853,7 +210235,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -208892,7 +210276,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -208931,7 +210317,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -208970,7 +210358,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -209009,7 +210399,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -209048,7 +210440,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -209087,7 +210481,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -209126,7 +210522,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -209165,7 +210563,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -209204,7 +210604,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -209243,7 +210645,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -209282,7 +210686,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -209321,7 +210727,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -209360,7 +210768,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -209399,7 +210809,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -209438,7 +210850,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -209477,7 +210891,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -209516,7 +210932,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -209555,7 +210973,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -209594,7 +211014,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -209633,7 +211055,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -209672,7 +211096,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -209711,7 +211137,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -209750,7 +211178,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -209789,7 +211219,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -209828,7 +211260,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -209867,7 +211301,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -209906,7 +211342,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -209945,7 +211383,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -209984,7 +211424,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -210023,7 +211465,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -210062,7 +211506,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -210101,7 +211547,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -210140,7 +211588,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -210179,7 +211629,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -210218,7 +211670,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -210257,7 +211711,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -210296,7 +211752,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -210335,7 +211793,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -210374,7 +211834,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -210413,7 +211875,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -210452,7 +211916,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -210491,7 +211957,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -210530,7 +211998,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -210569,7 +212039,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -210608,7 +212080,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -210647,7 +212121,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -210686,7 +212162,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -210725,7 +212203,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -210764,7 +212244,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -210803,7 +212285,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -210842,7 +212326,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -210881,7 +212367,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -210920,7 +212408,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -210959,7 +212449,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -210998,7 +212490,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -211037,7 +212531,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -211076,7 +212572,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -211115,7 +212613,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -211154,7 +212654,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -211193,7 +212695,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -211232,7 +212736,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -211271,7 +212777,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -211310,7 +212818,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -211349,7 +212859,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -211388,7 +212900,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -211427,7 +212941,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -211466,7 +212982,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -211505,7 +213023,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -211544,7 +213064,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -211583,7 +213105,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -211634,7 +213158,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -211673,7 +213199,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -211712,7 +213240,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -211751,7 +213281,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -211790,7 +213322,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -211829,7 +213363,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -211868,7 +213404,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -211907,7 +213445,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -211946,7 +213486,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -211985,7 +213527,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -212024,7 +213568,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -212063,7 +213609,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -212102,7 +213650,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -212141,7 +213691,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -212180,7 +213732,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -212219,7 +213773,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -212258,7 +213814,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -212297,7 +213855,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -212336,7 +213896,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -212375,7 +213937,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -212414,7 +213978,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -212453,7 +214019,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -212492,7 +214060,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -212531,7 +214101,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -212570,7 +214142,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -212609,7 +214183,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -212648,7 +214224,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -212687,7 +214265,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -212726,7 +214306,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -212765,7 +214347,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -212804,7 +214388,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -212844,7 +214430,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -212884,7 +214472,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -212924,7 +214514,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -212964,7 +214556,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -213004,7 +214598,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -213044,7 +214640,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -213083,7 +214681,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -213122,7 +214722,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -213161,7 +214763,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -213200,7 +214804,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -213239,7 +214845,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -213278,7 +214886,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -213317,7 +214927,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -213357,7 +214969,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -213397,7 +215011,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -213437,7 +215053,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -213477,7 +215095,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -213517,7 +215137,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -213556,7 +215178,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -213595,7 +215219,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -213634,7 +215260,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -213673,7 +215301,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -213712,7 +215342,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -213751,7 +215383,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -213790,7 +215424,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -213829,7 +215465,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -213868,7 +215506,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -213907,7 +215547,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -213946,7 +215588,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -213985,7 +215629,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -214024,7 +215670,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -214064,7 +215712,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -214104,7 +215754,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -214144,7 +215796,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -214184,7 +215838,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -214224,7 +215880,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -214264,7 +215922,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -214303,7 +215963,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -214342,7 +216004,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -214381,7 +216045,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -214420,7 +216086,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -214459,7 +216127,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -214498,7 +216168,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -214537,7 +216209,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -214576,7 +216250,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -214615,7 +216291,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -214654,7 +216332,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -214693,7 +216373,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -214732,7 +216414,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -214771,7 +216455,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -214810,7 +216496,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -214849,7 +216537,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -214888,7 +216578,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -214927,7 +216619,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -214966,7 +216660,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -215005,7 +216701,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -215044,7 +216742,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -215083,7 +216783,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -215122,7 +216824,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -215161,7 +216865,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -215200,7 +216906,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -215239,7 +216947,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -215278,7 +216988,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -215317,7 +217029,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -215356,7 +217070,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -215395,7 +217111,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -215434,7 +217152,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -215473,7 +217193,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -215512,7 +217234,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -215551,7 +217275,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -215590,7 +217316,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -215629,7 +217357,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -215668,7 +217398,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -215707,7 +217439,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -215746,7 +217480,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -215785,7 +217521,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -215824,7 +217562,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -215863,7 +217603,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -215902,7 +217644,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -215941,7 +217685,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -215980,7 +217726,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -216019,7 +217767,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -216058,7 +217808,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -216097,7 +217849,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -216136,7 +217890,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -216175,7 +217931,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -216214,7 +217972,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -216253,7 +218013,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -216292,7 +218054,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -216331,7 +218095,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -216370,7 +218136,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -216409,7 +218177,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -216448,7 +218218,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -216487,7 +218259,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -216526,7 +218300,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -216565,7 +218341,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -216604,7 +218382,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -216643,7 +218423,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -216682,7 +218464,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -216721,7 +218505,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -216760,7 +218546,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -216799,7 +218587,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -216838,7 +218628,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -216877,7 +218669,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -216916,7 +218710,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -216955,7 +218751,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -216994,7 +218792,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 844e651..664c143 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -39209,7 +39209,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -39248,7 +39250,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -39287,7 +39291,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -39326,7 +39332,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -39365,7 +39373,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -39404,7 +39414,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -39443,7 +39455,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -39482,7 +39496,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -39521,7 +39537,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -39560,7 +39578,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -39599,7 +39619,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -39638,7 +39660,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -39677,7 +39701,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -39716,7 +39742,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -39755,7 +39783,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -39794,7 +39824,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -39833,7 +39865,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -39891,7 +39925,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -39927,7 +39963,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -39963,7 +40001,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -39999,7 +40039,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -40035,7 +40077,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -40071,7 +40115,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -40107,7 +40153,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -40143,7 +40191,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -40179,7 +40229,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -40215,7 +40267,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -40251,7 +40305,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -40287,7 +40343,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -40323,7 +40381,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -40359,7 +40419,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -40395,7 +40457,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -40431,7 +40495,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -40467,7 +40533,9 @@
       {
         "args": [
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 0c0bcf7f..c7f2d68 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -2339,6 +2339,53 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "name": "site_per_process_android_browsertests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "android_browsertests",
+        "test_target": "//chrome/test:android_browsertests"
+      },
+      {
+        "args": [
+          "--site-per-process"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "name": "site_per_process_chrome_public_test_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 20
+        },
+        "test": "chrome_public_test_apk",
+        "test_target": "//chrome/android:chrome_public_test_apk"
+      },
+      {
+        "args": [
+          "--site-per-process"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
         "name": "site_per_process_components_browsertests",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -2411,6 +2458,30 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
+        "name": "site_per_process_content_shell_test_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 3
+        },
+        "test": "content_shell_test_apk",
+        "test_target": "//content/shell/android:content_shell_test_apk"
+      },
+      {
+        "args": [
+          "--site-per-process"
+        ],
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
         "name": "site_per_process_content_unittests",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -14522,7 +14593,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "base_unittests",
@@ -14562,7 +14635,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "boringssl_crypto_tests",
@@ -14602,7 +14677,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "boringssl_ssl_tests",
@@ -14642,7 +14719,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "components_unittests",
@@ -14682,7 +14761,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "crypto_unittests",
@@ -14722,7 +14803,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "gfx_unittests",
@@ -14762,7 +14845,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "google_apis_unittests",
@@ -14802,7 +14887,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
@@ -14842,7 +14929,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_integration_eg2tests_module",
@@ -14883,7 +14972,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_settings_eg2tests_module",
@@ -14923,7 +15014,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_signin_eg2tests_module",
@@ -14963,7 +15056,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
@@ -15003,7 +15098,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_ui_eg2tests_module",
@@ -15044,7 +15141,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_unittests",
@@ -15084,7 +15183,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_chrome_web_eg2tests_module",
@@ -15124,7 +15225,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_components_unittests",
@@ -15164,7 +15267,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_net_unittests",
@@ -15204,7 +15309,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_remoting_unittests",
@@ -15244,7 +15351,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_showcase_eg2tests_module",
@@ -15284,7 +15393,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_testing_unittests",
@@ -15324,7 +15435,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_web_inttests",
@@ -15364,7 +15477,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_web_shell_eg2tests_module",
@@ -15404,7 +15519,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_web_unittests",
@@ -15444,7 +15561,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_web_view_inttests",
@@ -15484,7 +15603,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ios_web_view_unittests",
@@ -15524,7 +15645,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "net_unittests",
@@ -15564,7 +15687,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "services_unittests",
@@ -15604,7 +15729,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "skia_unittests",
@@ -15644,7 +15771,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "sql_unittests",
@@ -15684,7 +15813,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "ui_base_unittests",
@@ -15724,7 +15855,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_coverage_data": true,
         "isolate_name": "url_unittests",
@@ -15768,7 +15901,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "cronet_test",
         "merge": {
@@ -15807,7 +15942,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "cronet_test",
         "merge": {
@@ -15852,7 +15989,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -15893,7 +16032,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -15934,7 +16075,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -15975,7 +16118,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -16016,7 +16161,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -16057,7 +16204,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -16098,7 +16247,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -16139,7 +16290,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -16180,7 +16333,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -16221,7 +16376,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -16262,7 +16419,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -16303,7 +16462,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -16344,7 +16505,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -16385,7 +16548,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -16426,7 +16591,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -16467,7 +16634,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -16508,7 +16677,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -16550,7 +16721,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -16592,7 +16765,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -16633,7 +16808,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -16674,7 +16851,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -16716,7 +16895,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -16758,7 +16939,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -16799,7 +16982,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -16840,7 +17025,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -16881,7 +17068,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -16922,7 +17111,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -16964,7 +17155,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -17006,7 +17199,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -17047,7 +17242,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -17088,7 +17285,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -17129,7 +17328,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -17170,7 +17371,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -17211,7 +17414,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -17252,7 +17457,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -17293,7 +17500,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -17334,7 +17543,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -17375,7 +17586,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -17416,7 +17629,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -17457,7 +17672,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -17498,7 +17715,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -17539,7 +17758,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -17580,7 +17801,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -17621,7 +17844,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -17662,7 +17887,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -17703,7 +17930,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -17744,7 +17973,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -17785,7 +18016,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -17826,7 +18059,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -17867,7 +18102,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -17908,7 +18145,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -17949,7 +18188,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -17990,7 +18231,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -18031,7 +18274,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -18072,7 +18317,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -18113,7 +18360,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -18154,7 +18403,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -18195,7 +18446,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -18236,7 +18489,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -18277,7 +18532,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -18318,7 +18575,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -18359,7 +18618,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -18400,7 +18661,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -18441,7 +18704,9 @@
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -18487,7 +18752,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -18526,7 +18793,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -18565,7 +18834,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -18604,7 +18875,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -18643,7 +18916,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -18682,7 +18957,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -18721,7 +18998,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -18760,7 +19039,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -18799,7 +19080,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -18838,7 +19121,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -18877,7 +19162,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -18916,7 +19203,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -18955,7 +19244,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -18994,7 +19285,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -19033,7 +19326,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -19072,7 +19367,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -19111,7 +19408,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -19150,7 +19449,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -19189,7 +19490,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -19228,7 +19531,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -19267,7 +19572,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -19306,7 +19613,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -19345,7 +19654,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -19384,7 +19695,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -19423,7 +19736,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -19462,7 +19777,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -19501,7 +19818,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -19540,7 +19859,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -19579,7 +19900,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -19618,7 +19941,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -19657,7 +19982,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -19696,7 +20023,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -19735,7 +20064,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -19774,7 +20105,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -19813,7 +20146,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -19852,7 +20187,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -19892,7 +20229,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -19932,7 +20271,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -19972,7 +20313,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -20012,7 +20355,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -20052,7 +20397,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -20092,7 +20439,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -20132,7 +20481,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -20172,7 +20523,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -20212,7 +20565,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -20251,7 +20606,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -20290,7 +20647,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -20329,7 +20688,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -20368,7 +20729,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -20407,7 +20770,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -20446,7 +20811,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -20485,7 +20852,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -20524,7 +20893,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -20563,7 +20934,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -20603,7 +20976,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -20643,7 +21018,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -20683,7 +21060,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -20723,7 +21102,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -20762,7 +21143,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -20801,7 +21184,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -20840,7 +21225,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -20879,7 +21266,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -20918,7 +21307,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -20957,7 +21348,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -20996,7 +21389,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -21035,7 +21430,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -21074,7 +21471,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -21113,7 +21512,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -21152,7 +21553,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -21191,7 +21594,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -21230,7 +21635,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -21269,7 +21676,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -21308,7 +21717,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -21347,7 +21758,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -21386,7 +21799,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -21425,7 +21840,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -21465,7 +21882,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -21505,7 +21924,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -21545,7 +21966,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -21585,7 +22008,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -21625,7 +22050,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -21665,7 +22092,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -21705,7 +22134,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -21745,7 +22176,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -21785,7 +22218,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -21824,7 +22259,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -21863,7 +22300,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -21902,7 +22341,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -21941,7 +22382,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -21980,7 +22423,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -22019,7 +22464,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -22058,7 +22505,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -22097,7 +22546,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -22136,7 +22587,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -22175,7 +22628,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -22214,7 +22669,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -22253,7 +22710,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -22292,7 +22751,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -22331,7 +22792,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -22370,7 +22833,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -22409,7 +22874,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -22448,7 +22915,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -22487,7 +22956,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -22526,7 +22997,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -22565,7 +23038,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -22604,7 +23079,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -22643,7 +23120,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -22682,7 +23161,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -22721,7 +23202,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -22760,7 +23243,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -22799,7 +23284,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -22838,7 +23325,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -22877,7 +23366,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -22916,7 +23407,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -22955,7 +23448,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -22994,7 +23489,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -23033,7 +23530,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -23072,7 +23571,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -23111,7 +23612,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -23150,7 +23653,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -23189,7 +23694,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -23228,7 +23735,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -23267,7 +23776,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -23306,7 +23817,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -23345,7 +23858,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -23384,7 +23899,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -23423,7 +23940,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -23462,7 +23981,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -23501,7 +24022,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -23540,7 +24063,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -23579,7 +24104,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -23618,7 +24145,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -23657,7 +24186,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -23696,7 +24227,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -23735,7 +24268,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -23774,7 +24309,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -23813,7 +24350,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -23852,7 +24391,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -23891,7 +24432,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -23930,7 +24473,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -23969,7 +24514,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -24008,7 +24555,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -24047,7 +24596,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -24086,7 +24637,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -24125,7 +24678,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -24164,7 +24719,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -24203,7 +24760,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -24242,7 +24801,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -24281,7 +24842,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -24320,7 +24883,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -24359,7 +24924,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -24398,7 +24965,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -24437,7 +25006,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -24476,7 +25047,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -24515,7 +25088,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -24554,7 +25129,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -24593,7 +25170,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -24632,7 +25211,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -24671,7 +25252,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -24710,7 +25293,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -24749,7 +25334,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -24788,7 +25375,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -24827,7 +25416,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -24866,7 +25457,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -24905,7 +25498,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -24944,7 +25539,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -24983,7 +25580,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -25022,7 +25621,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -25061,7 +25662,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -25112,7 +25715,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -25151,7 +25756,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -25190,7 +25797,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -25229,7 +25838,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -25268,7 +25879,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -25307,7 +25920,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -25346,7 +25961,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -25385,7 +26002,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -25424,7 +26043,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -25463,7 +26084,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -25502,7 +26125,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -25541,7 +26166,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -25580,7 +26207,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -25619,7 +26248,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -25658,7 +26289,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -25697,7 +26330,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -25736,7 +26371,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -25775,7 +26412,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -25814,7 +26453,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -25853,7 +26494,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -25892,7 +26535,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -25931,7 +26576,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -25970,7 +26617,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -26009,7 +26658,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -26048,7 +26699,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
@@ -26087,7 +26740,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -26126,7 +26781,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -26165,7 +26822,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -26204,7 +26863,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -26243,7 +26904,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -26282,7 +26945,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -26322,7 +26987,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
@@ -26362,7 +27029,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -26402,7 +27071,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -26442,7 +27113,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -26482,7 +27155,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -26522,7 +27197,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -26561,7 +27238,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -26600,7 +27279,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -26639,7 +27320,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -26678,7 +27361,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -26717,7 +27402,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -26756,7 +27443,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
@@ -26795,7 +27484,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -26835,7 +27526,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -26875,7 +27568,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -26915,7 +27610,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -26955,7 +27652,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -26995,7 +27694,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -27034,7 +27735,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
@@ -27073,7 +27776,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -27112,7 +27817,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -27151,7 +27858,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -27190,7 +27899,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -27229,7 +27940,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -27268,7 +27981,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
@@ -27307,7 +28022,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -27346,7 +28063,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -27385,7 +28104,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -27424,7 +28145,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -27463,7 +28186,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -27502,7 +28227,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -27542,7 +28269,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
@@ -27582,7 +28311,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -27622,7 +28353,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -27662,7 +28395,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -27702,7 +28437,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -27742,7 +28479,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -27781,7 +28520,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -27820,7 +28561,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -27859,7 +28602,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -27898,7 +28643,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -27937,7 +28684,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -27976,7 +28725,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
@@ -28015,7 +28766,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -28054,7 +28807,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -28093,7 +28848,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -28132,7 +28889,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -28171,7 +28930,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -28210,7 +28971,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -28249,7 +29012,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -28288,7 +29053,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -28327,7 +29094,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -28366,7 +29135,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -28405,7 +29176,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -28444,7 +29217,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -28483,7 +29258,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
@@ -28522,7 +29299,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -28561,7 +29340,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -28600,7 +29381,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -28639,7 +29422,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -28678,7 +29463,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -28717,7 +29504,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -28756,7 +29545,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -28795,7 +29586,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -28834,7 +29627,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -28873,7 +29668,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -28912,7 +29709,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -28951,7 +29750,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -28990,7 +29791,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -29029,7 +29832,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
@@ -29068,7 +29873,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -29107,7 +29914,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -29146,7 +29955,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -29185,7 +29996,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -29224,7 +30037,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -29263,7 +30078,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -29302,7 +30119,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -29341,7 +30160,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -29380,7 +30201,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -29419,7 +30242,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -29458,7 +30283,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -29497,7 +30324,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -29536,7 +30365,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -29575,7 +30406,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -29614,7 +30447,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -29653,7 +30488,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -29692,7 +30529,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -29731,7 +30570,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -29770,7 +30611,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -29809,7 +30652,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -29848,7 +30693,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -29887,7 +30734,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -29926,7 +30775,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -29965,7 +30816,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -30004,7 +30857,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -30043,7 +30898,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -30082,7 +30939,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -30121,7 +30980,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -30160,7 +31021,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -30199,7 +31062,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -30238,7 +31103,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -30277,7 +31144,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -30316,7 +31185,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -30355,7 +31226,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -30394,7 +31267,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -30433,7 +31308,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -30472,7 +31349,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 1993830fe..358519fa 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -1754,6 +1754,631 @@
   "Fuchsia ARM64": {
     "additional_compile_targets": [
       "all"
+    ],
+    "gtest_tests": [
+      {
+        "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": "angle_unittests",
+        "test_target": "//third_party/angle/src/tests:angle_unittests"
+      },
+      {
+        "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": "base_unittests",
+        "test_target": "//base:base_unittests"
+      },
+      {
+        "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": "base_util_unittests",
+        "test_target": "//base/util:base_util_unittests"
+      },
+      {
+        "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": "blink_common_unittests",
+        "test_target": "//third_party/blink/common:blink_common_unittests"
+      },
+      {
+        "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": "blink_heap_unittests",
+        "test_target": "//third_party/blink/renderer/platform/heap:blink_heap_unittests"
+      },
+      {
+        "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": "blink_platform_unittests",
+        "test_target": "//third_party/blink/renderer/platform:blink_platform_unittests"
+      },
+      {
+        "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": "cast_runner_browsertests",
+        "test_target": "//fuchsia/runners:cast_runner_browsertests"
+      },
+      {
+        "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": "cast_runner_integration_tests",
+        "test_target": "//fuchsia/runners:cast_runner_integration_tests"
+      },
+      {
+        "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": "cast_runner_unittests",
+        "test_target": "//fuchsia/runners:cast_runner_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter"
+        ],
+        "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": "content_unittests",
+        "test_target": "//content/test:content_unittests"
+      },
+      {
+        "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": "cr_fuchsia_base_unittests",
+        "test_target": "//fuchsia/base:cr_fuchsia_base_unittests"
+      },
+      {
+        "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": "cronet_tests",
+        "test_target": "//components/cronet:cronet_tests"
+      },
+      {
+        "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": "cronet_unittests",
+        "test_target": "//components/cronet:cronet_unittests"
+      },
+      {
+        "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": "crypto_unittests",
+        "test_target": "//crypto:crypto_unittests"
+      },
+      {
+        "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": "events_unittests",
+        "test_target": "//ui/events:events_unittests"
+      },
+      {
+        "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": "gfx_unittests",
+        "test_target": "//ui/gfx:gfx_unittests"
+      },
+      {
+        "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": "gpu_unittests",
+        "test_target": "//gpu:gpu_unittests"
+      },
+      {
+        "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": "http_service_tests",
+        "test_target": "//fuchsia/http:http_service_tests"
+      },
+      {
+        "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": "ipc_tests",
+        "test_target": "//ipc:ipc_tests"
+      },
+      {
+        "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_target": "//media:media_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.mojo_unittests.filter"
+        ],
+        "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": "mojo_unittests",
+        "test_target": "//mojo:mojo_unittests"
+      },
+      {
+        "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": "perfetto_unittests",
+        "test_target": "//third_party/perfetto:perfetto_unittests"
+      },
+      {
+        "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": "service_manager_unittests",
+        "test_target": "//services/service_manager/tests:service_manager_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.services_unittests.filter"
+        ],
+        "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": "services_unittests",
+        "test_target": "//services:services_unittests"
+      },
+      {
+        "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": "skia_unittests",
+        "test_target": "//skia:skia_unittests"
+      },
+      {
+        "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": "sql_unittests",
+        "test_target": "//sql:sql_unittests"
+      },
+      {
+        "args": [
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter"
+        ],
+        "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": "ui_base_unittests",
+        "test_target": "//ui/base:ui_base_unittests"
+      },
+      {
+        "args": [
+          "--child-arg=--ozone-platform=headless"
+        ],
+        "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": "viz_unittests",
+        "test_target": "//components/viz:viz_unittests"
+      },
+      {
+        "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": "web_engine_browsertests",
+        "test_target": "//fuchsia/engine:web_engine_browsertests"
+      },
+      {
+        "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": "web_engine_integration_tests",
+        "test_target": "//fuchsia/engine:web_engine_integration_tests"
+      },
+      {
+        "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": "web_engine_unittests",
+        "test_target": "//fuchsia/engine:web_engine_unittests"
+      },
+      {
+        "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": "web_runner_integration_tests",
+        "test_target": "//fuchsia/runners:web_runner_integration_tests"
+      }
     ]
   },
   "Fuchsia x64": {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 71e035d..5b009ff 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -12077,7 +12077,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -12116,7 +12118,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -12155,7 +12159,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -12194,7 +12200,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "base_unittests",
         "merge": {
@@ -12233,7 +12241,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -12272,7 +12282,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
@@ -12311,7 +12323,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -12350,7 +12364,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
@@ -12389,7 +12405,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -12428,7 +12446,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -12467,7 +12487,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -12506,7 +12528,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "components_unittests",
         "merge": {
@@ -12545,7 +12569,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -12584,7 +12610,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
@@ -12623,7 +12651,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -12662,7 +12692,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -12701,7 +12733,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -12740,7 +12774,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
@@ -12779,7 +12815,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -12818,7 +12856,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
@@ -12857,7 +12897,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -12897,7 +12939,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -12937,7 +12981,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -12976,7 +13022,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -13015,7 +13063,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -13055,7 +13105,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -13095,7 +13147,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -13134,7 +13188,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -13173,7 +13229,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -13212,7 +13270,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
@@ -13251,7 +13311,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -13290,7 +13352,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
@@ -13329,7 +13393,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -13368,7 +13434,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
@@ -13407,7 +13475,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -13446,7 +13516,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
@@ -13485,7 +13557,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -13524,7 +13598,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
@@ -13563,7 +13639,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -13602,7 +13680,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -13641,7 +13721,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -13680,7 +13762,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
@@ -13719,7 +13803,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -13758,7 +13844,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -13797,7 +13885,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -13836,7 +13926,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -13875,7 +13967,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -13914,7 +14008,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
@@ -13953,7 +14049,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -13992,7 +14090,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -14031,7 +14131,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -14070,7 +14172,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
@@ -14109,7 +14213,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -14148,7 +14254,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -14187,7 +14295,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -14226,7 +14336,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
@@ -14265,7 +14377,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -14304,7 +14418,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "net_unittests",
         "merge": {
@@ -14343,7 +14459,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -14382,7 +14500,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "services_unittests",
         "merge": {
@@ -14421,7 +14541,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -14460,7 +14582,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -14499,7 +14623,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -14538,7 +14664,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
@@ -14577,7 +14705,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -14616,7 +14746,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
@@ -14655,7 +14787,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -14694,7 +14828,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -14733,7 +14869,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -14772,7 +14910,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
@@ -14811,7 +14951,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -14850,7 +14992,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "url_unittests",
         "merge": {
@@ -14896,7 +15040,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -14935,7 +15081,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -14974,7 +15122,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -15013,7 +15163,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -15052,7 +15204,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_bookmarks_egtests",
         "merge": {
@@ -15091,7 +15245,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -15131,7 +15287,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -15171,7 +15329,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_integration_egtests",
         "merge": {
@@ -15211,7 +15371,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -15250,7 +15412,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -15289,7 +15453,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -15328,7 +15494,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -15367,7 +15535,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_reading_list_egtests",
         "merge": {
@@ -15406,7 +15576,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -15446,7 +15618,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -15486,7 +15660,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -15526,7 +15702,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -15566,7 +15744,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_settings_egtests",
         "merge": {
@@ -15606,7 +15786,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -15645,7 +15827,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -15684,7 +15868,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_signin_egtests",
         "merge": {
@@ -15723,7 +15909,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -15762,7 +15950,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -15801,7 +15991,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -15840,7 +16032,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -15879,7 +16073,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_translate_egtests",
         "merge": {
@@ -15918,7 +16114,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -15958,7 +16156,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -15998,7 +16198,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_ui_egtests",
         "merge": {
@@ -16038,7 +16240,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -16077,7 +16281,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -16116,7 +16322,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -16155,7 +16363,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -16194,7 +16404,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_chrome_web_egtests",
         "merge": {
@@ -16233,7 +16445,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -16272,7 +16486,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -16311,7 +16527,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -16350,7 +16568,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -16389,7 +16609,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_showcase_egtests",
         "merge": {
@@ -16428,7 +16650,9 @@
           "--version",
           "12.4",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -16467,7 +16691,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
@@ -16506,7 +16732,9 @@
           "--version",
           "13.3",
           "--out-dir",
-          "${ISOLATED_OUTDIR}"
+          "${ISOLATED_OUTDIR}",
+          "--xcode-build-version",
+          "11c29"
         ],
         "isolate_name": "ios_web_shell_egtests",
         "merge": {
diff --git a/testing/buildbot/chromium.try.json b/testing/buildbot/chromium.try.json
index 5360dcd4..f641503 100644
--- a/testing/buildbot/chromium.try.json
+++ b/testing/buildbot/chromium.try.json
@@ -197,7 +197,7 @@
       {
         "args": [
           "--num-retries=3",
-          "--additional-driver-flag=--enable-blink-features=EditingNGruntime"
+          "--additional-driver-flag=--enable-blink-features=EditingNG"
         ],
         "isolate_name": "blink_web_tests",
         "merge": {
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 59278e6d..0893b78 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -789,6 +789,12 @@
     },
   },
   'xcode_11c29': {
+    '$mixin_append': {
+      'args': [
+        '--xcode-build-version',
+        '11c29'
+      ],
+    },
     'swarming': {
       'named_caches': [
         {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 3f3ac596..4784d1d4 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -339,7 +339,7 @@
       },
       'linux-layout-tests-edit-ng': {
         'args': [
-          '--additional-driver-flag=--enable-blink-features=EditingNGruntime',
+          '--additional-driver-flag=--enable-blink-features=EditingNG',
         ],
       },
       'linux-layout-tests-fragment-item': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 6bcf292..ee05a753 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3234,6 +3234,24 @@
     },
 
     'site_isolation_android_fyi_gtests': {
+      'site_per_process_android_browsertests': {
+        'args': [
+          '--site-per-process',
+        ],
+        'swarming': {
+          'shards': 1,
+        },
+        'test': 'android_browsertests',
+      },
+      'site_per_process_chrome_public_test_apk': {
+        'args': [
+          '--site-per-process',
+        ],
+        'swarming': {
+          'shards': 20,
+        },
+        'test': 'chrome_public_test_apk',
+      },
       'site_per_process_components_browsertests': {
         'args': [
           '--site-per-process',
@@ -3260,6 +3278,15 @@
         },
         'test': 'content_browsertests',
       },
+      'site_per_process_content_shell_test_apk': {
+        'args': [
+          '--site-per-process',
+        ],
+        'swarming': {
+          'shards': 3,
+        },
+        'test': 'content_shell_test_apk',
+      },
       'site_per_process_content_unittests': {
         'args': [
           '--site-per-process'
diff --git a/testing/buildbot/tryserver.chromium.linux.json b/testing/buildbot/tryserver.chromium.linux.json
index 390a8c2..fe0264b 100644
--- a/testing/buildbot/tryserver.chromium.linux.json
+++ b/testing/buildbot/tryserver.chromium.linux.json
@@ -14,7 +14,7 @@
       {
         "args": [
           "--num-retries=3",
-          "--additional-driver-flag=--enable-blink-features=EditingNGruntime"
+          "--additional-driver-flag=--enable-blink-features=EditingNG"
         ],
         "isolate_name": "blink_web_tests",
         "merge": {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 5aa9b46..d7435a6 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -3863,6 +3863,14 @@
         'additional_compile_targets': [
           'all',
         ],
+        'test_suites': {
+          'gtest_tests': 'fuchsia_gtests',
+        },
+        'mixins': [
+          'arm64',
+          'docker',
+          'linux-xenial',
+        ],
       },
       'Fuchsia x64': {
         'additional_compile_targets': [
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index f5dcc05..4d63da6 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -60,6 +60,7 @@
     "css/navigation_controls.h",
     "css/page_size_type.h",
     "css/preferred_color_scheme.h",
+    "css/screen_spanning.h",
     "device_memory/approximated_device_memory.h",
     "dom_storage/session_storage_namespace_id.h",
     "experiments/memory_ablation_experiment.h",
diff --git a/third_party/blink/public/common/css/screen_spanning.h b/third_party/blink/public/common/css/screen_spanning.h
new file mode 100644
index 0000000..6b3f5d0a
--- /dev/null
+++ b/third_party/blink/public/common/css/screen_spanning.h
@@ -0,0 +1,14 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_CSS_SCREEN_SPANNING_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_CSS_SCREEN_SPANNING_H_
+
+namespace blink {
+
+enum class ScreenSpanning { kNone, kSingleFoldHorizontal, kSingleFoldVertical };
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_CSS_SCREEN_SPANNING_H_
diff --git a/third_party/blink/renderer/core/css/css_value_keywords.json5 b/third_party/blink/renderer/core/css/css_value_keywords.json5
index 3b7a8b92..ccea5247 100644
--- a/third_party/blink/renderer/core/css/css_value_keywords.json5
+++ b/third_party/blink/renderer/core/css/css_value_keywords.json5
@@ -1231,5 +1231,10 @@
     // @supports selector(...)
     // https://drafts.csswg.org/css-conditional-4/#typedef-supports-selector-fn
     "selector",
+
+    // (screen-spanning) media feature
+    // none
+    "single-fold-vertical",
+    "single-fold-horizontal",
   ],
 }
diff --git a/third_party/blink/renderer/core/css/media_feature_names.json5 b/third_party/blink/renderer/core/css/media_feature_names.json5
index cd214bc0f..388a588 100644
--- a/third_party/blink/renderer/core/css/media_feature_names.json5
+++ b/third_party/blink/renderer/core/css/media_feature_names.json5
@@ -57,6 +57,7 @@
     "resolution",
     "-webkit-transform-3d",
     "scan",
+    "screen-spanning",
     "shape",
   ],
 }
diff --git a/third_party/blink/renderer/core/css/media_query_evaluator.cc b/third_party/blink/renderer/core/css/media_query_evaluator.cc
index 1a091ab8..a2a1cea5 100644
--- a/third_party/blink/renderer/core/css/media_query_evaluator.cc
+++ b/third_party/blink/renderer/core/css/media_query_evaluator.cc
@@ -32,6 +32,7 @@
 #include "third_party/blink/public/common/css/forced_colors.h"
 #include "third_party/blink/public/common/css/navigation_controls.h"
 #include "third_party/blink/public/common/css/preferred_color_scheme.h"
+#include "third_party/blink/public/common/css/screen_spanning.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
 #include "third_party/blink/public/platform/pointer_properties.h"
 #include "third_party/blink/public/platform/shape_properties.h"
@@ -901,6 +902,26 @@
           value.id == CSSValueID::kBackButton);
 }
 
+static bool ScreenSpanningMediaFeatureEval(const MediaQueryExpValue& value,
+                                           MediaFeaturePrefix,
+                                           const MediaValues& media_values) {
+  ScreenSpanning screen_spanning_mode = media_values.GetScreenSpanning();
+
+  if (!value.IsValid())
+    return screen_spanning_mode != ScreenSpanning::kNone;
+
+  // We should not have parsed a valid MediaQueryExpValue if the value is not
+  // an identifier.
+  DCHECK(value.is_id);
+
+  return (screen_spanning_mode == ScreenSpanning::kNone &&
+          value.id == CSSValueID::kNone) ||
+         (screen_spanning_mode == ScreenSpanning::kSingleFoldVertical &&
+          value.id == CSSValueID::kSingleFoldVertical) ||
+         (screen_spanning_mode == ScreenSpanning::kSingleFoldHorizontal &&
+          value.id == CSSValueID::kSingleFoldHorizontal);
+}
+
 void MediaQueryEvaluator::Init() {
   // Create the table.
   g_function_map = new FunctionMap;
diff --git a/third_party/blink/renderer/core/css/media_query_evaluator_test.cc b/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
index 998370f..bb2e9e00 100644
--- a/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
+++ b/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/css/forced_colors.h"
+#include "third_party/blink/public/common/css/screen_spanning.h"
 #include "third_party/blink/renderer/core/css/media_list.h"
 #include "third_party/blink/renderer/core/css/media_values_cached.h"
 #include "third_party/blink/renderer/core/css/media_values_initial_viewport.h"
@@ -199,6 +200,32 @@
     {nullptr, 0}  // Do not remove the terminator line.
 };
 
+MediaQueryEvaluatorTestCase g_screen_spanning_none_cases[] = {
+    {"(screen-spanning)", 0},
+    {"(screen-spanning: single-fold-vertical)", 0},
+    {"(screen-spanning: single-fold-horizontal)", 0},
+    {"(screen-spanning: none)", 1},
+    {"(screen-spanning: 1px)", 0},
+    {"(screen-spanning: 16/9)", 0},
+    {nullptr, 0}  // Do not remove the terminator line.
+};
+
+MediaQueryEvaluatorTestCase g_screen_spanning_single_fold_vertical_cases[] = {
+    {"(screen-spanning)", 1},
+    {"(screen-spanning: single-fold-vertical)", 1},
+    {"(screen-spanning: single-fold-horizontal)", 0},
+    {"(screen-spanning: none)", 0},
+    {nullptr, 0}  // Do not remove the terminator line.
+};
+
+MediaQueryEvaluatorTestCase g_screen_spanning_single_fold_horizontal_cases[] = {
+    {"(screen-spanning)", 1},
+    {"(screen-spanning: single-fold-vertical)", 0},
+    {"(screen-spanning: single-fold-horizontal)", 1},
+    {"(screen-spanning: none)", 0},
+    {nullptr, 0}  // Do not remove the terminator line.
+};
+
 void TestMQEvaluator(MediaQueryEvaluatorTestCase* test_cases,
                      const MediaQueryEvaluator& media_query_evaluator,
                      CSSParserMode mode) {
@@ -373,4 +400,33 @@
   }
 }
 
+TEST(MediaQueryEvaluatorTest, CachedScreenSpanning) {
+  ScopedCSSFoldablesForTest scoped_feature(true);
+
+  MediaValuesCached::MediaValuesCachedData data;
+  {
+    data.screen_spanning = ScreenSpanning::kNone;
+    MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
+
+    MediaQueryEvaluator media_query_evaluator(*media_values);
+    TestMQEvaluator(g_screen_spanning_none_cases, media_query_evaluator);
+  }
+
+  {
+    data.screen_spanning = ScreenSpanning::kSingleFoldVertical;
+    MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
+    MediaQueryEvaluator media_query_evaluator(*media_values);
+    TestMQEvaluator(g_screen_spanning_single_fold_vertical_cases,
+                    media_query_evaluator);
+  }
+
+  {
+    data.screen_spanning = ScreenSpanning::kSingleFoldHorizontal;
+    MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
+    MediaQueryEvaluator media_query_evaluator(*media_values);
+    TestMQEvaluator(g_screen_spanning_single_fold_horizontal_cases,
+                    media_query_evaluator);
+  }
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/media_query_exp.cc b/third_party/blink/renderer/core/css/media_query_exp.cc
index 37d0f166..e3ea6249 100644
--- a/third_party/blink/renderer/core/css/media_query_exp.cc
+++ b/third_party/blink/renderer/core/css/media_query_exp.cc
@@ -101,6 +101,14 @@
     }
   }
 
+  if (RuntimeEnabledFeatures::CSSFoldablesEnabled()) {
+    if (media_feature == media_feature_names::kScreenSpanningMediaFeature) {
+      return ident == CSSValueID::kNone ||
+             ident == CSSValueID::kSingleFoldVertical ||
+             ident == CSSValueID::kSingleFoldHorizontal;
+    }
+  }
+
   return false;
 }
 
@@ -224,7 +232,9 @@
           RuntimeEnabledFeatures::MediaQueryNavigationControlsEnabled()) ||
          (media_feature == media_feature_names::kOriginTrialTestMediaFeature &&
           RuntimeEnabledFeatures::OriginTrialsSampleAPIEnabled(
-              execution_context));
+              execution_context)) ||
+         (media_feature == media_feature_names::kScreenSpanningMediaFeature &&
+          RuntimeEnabledFeatures::CSSFoldablesEnabled());
 }
 
 bool MediaQueryExp::IsViewportDependent() const {
diff --git a/third_party/blink/renderer/core/css/media_query_set_test.cc b/third_party/blink/renderer/core/css/media_query_set_test.cc
index fc00218..1ccb196 100644
--- a/third_party/blink/renderer/core/css/media_query_set_test.cc
+++ b/third_party/blink/renderer/core/css/media_query_set_test.cc
@@ -194,6 +194,7 @@
   ScopedMediaQueryShapeForTest shape_flag(false);
   ScopedForcedColorsForTest forced_colors_flag(false);
   ScopedMediaQueryNavigationControlsForTest navigation_controls_flag(false);
+  ScopedCSSFoldablesForTest foldables_flag(false);
 
   // The first string represents the input string, the second string represents
   // the output string.
@@ -201,9 +202,11 @@
       {"(shape)", "not all"},
       {"(forced-colors)", "not all"},
       {"(navigation-controls)", "not all"},
+      {"(screen-spanning)", "not all"},
       {"(shape: rect)", "not all"},
       {"(forced-colors: none)", "not all"},
       {"(navigation-controls: none)", "not all"},
+      {"(screen-spanning:none)", "not all"},
       {nullptr, nullptr}  // Do not remove the terminator line.
   };
 
diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/blink/renderer/core/css/media_values.cc
index fda4355..b7ae26e 100644
--- a/third_party/blink/renderer/core/css/media_values.cc
+++ b/third_party/blink/renderer/core/css/media_values.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/css/media_values.h"
 
+#include "third_party/blink/public/common/css/screen_spanning.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_screen_info.h"
 #include "third_party/blink/public/platform/web_theme_engine.h"
@@ -227,6 +228,12 @@
   return frame->GetSettings()->GetNavigationControls();
 }
 
+ScreenSpanning MediaValues::CalculateScreenSpanning(LocalFrame* frame) {
+  // TODO(dlibby): Retrieve info propagated from the host as to our]
+  // screen-spanning state.
+  return ScreenSpanning::kNone;
+}
+
 bool MediaValues::ComputeLengthImpl(double value,
                                     CSSPrimitiveValue::UnitType type,
                                     unsigned default_font_size,
diff --git a/third_party/blink/renderer/core/css/media_values.h b/third_party/blink/renderer/core/css/media_values.h
index 9a774e6..7098dec 100644
--- a/third_party/blink/renderer/core/css/media_values.h
+++ b/third_party/blink/renderer/core/css/media_values.h
@@ -22,6 +22,7 @@
 enum class PreferredColorScheme;
 enum class ForcedColors;
 enum class NavigationControls;
+enum class ScreenSpanning;
 
 PreferredColorScheme CSSValueIDToPreferredColorScheme(CSSValueID id);
 
@@ -86,6 +87,7 @@
   virtual bool PrefersReducedMotion() const = 0;
   virtual ForcedColors GetForcedColors() const = 0;
   virtual NavigationControls GetNavigationControls() const = 0;
+  virtual ScreenSpanning GetScreenSpanning() const = 0;
 
  protected:
   static double CalculateViewportWidth(LocalFrame*);
@@ -111,6 +113,7 @@
   static bool CalculatePrefersReducedMotion(LocalFrame*);
   static ForcedColors CalculateForcedColors();
   static NavigationControls CalculateNavigationControls(LocalFrame*);
+  static ScreenSpanning CalculateScreenSpanning(LocalFrame*);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/media_values_cached.cc b/third_party/blink/renderer/core/css/media_values_cached.cc
index 0f9c299..725271e 100644
--- a/third_party/blink/renderer/core/css/media_values_cached.cc
+++ b/third_party/blink/renderer/core/css/media_values_cached.cc
@@ -7,6 +7,7 @@
 #include "third_party/blink/public/common/css/forced_colors.h"
 #include "third_party/blink/public/common/css/navigation_controls.h"
 #include "third_party/blink/public/common/css/preferred_color_scheme.h"
+#include "third_party/blink/public/common/css/screen_spanning.h"
 #include "third_party/blink/renderer/core/css/css_primitive_value.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -37,7 +38,8 @@
       preferred_color_scheme(PreferredColorScheme::kNoPreference),
       prefers_reduced_motion(false),
       forced_colors(ForcedColors::kNone),
-      navigation_controls(NavigationControls::kNone) {}
+      navigation_controls(NavigationControls::kNone),
+      screen_spanning(ScreenSpanning::kNone) {}
 
 MediaValuesCached::MediaValuesCachedData::MediaValuesCachedData(
     Document& document)
@@ -80,6 +82,7 @@
     prefers_reduced_motion = MediaValues::CalculatePrefersReducedMotion(frame);
     forced_colors = MediaValues::CalculateForcedColors();
     navigation_controls = MediaValues::CalculateNavigationControls(frame);
+    screen_spanning = MediaValues::CalculateScreenSpanning(frame);
   }
 }
 
@@ -210,4 +213,8 @@
   return data_.navigation_controls;
 }
 
+ScreenSpanning MediaValuesCached::GetScreenSpanning() const {
+  return data_.screen_spanning;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/media_values_cached.h b/third_party/blink/renderer/core/css/media_values_cached.h
index 4a82b2aa..cb0a896 100644
--- a/third_party/blink/renderer/core/css/media_values_cached.h
+++ b/third_party/blink/renderer/core/css/media_values_cached.h
@@ -40,6 +40,7 @@
     bool prefers_reduced_motion;
     ForcedColors forced_colors;
     NavigationControls navigation_controls;
+    ScreenSpanning screen_spanning;
 
     MediaValuesCachedData();
     explicit MediaValuesCachedData(Document&);
@@ -69,6 +70,7 @@
       data.prefers_reduced_motion = prefers_reduced_motion;
       data.forced_colors = forced_colors;
       data.navigation_controls = navigation_controls;
+      data.screen_spanning = screen_spanning;
       return data;
     }
   };
@@ -109,6 +111,7 @@
   bool PrefersReducedMotion() const override;
   ForcedColors GetForcedColors() const override;
   NavigationControls GetNavigationControls() const override;
+  ScreenSpanning GetScreenSpanning() const override;
 
   void OverrideViewportDimensions(double width, double height) override;
 
diff --git a/third_party/blink/renderer/core/css/media_values_dynamic.cc b/third_party/blink/renderer/core/css/media_values_dynamic.cc
index 0b80c39..1f1a000 100644
--- a/third_party/blink/renderer/core/css/media_values_dynamic.cc
+++ b/third_party/blink/renderer/core/css/media_values_dynamic.cc
@@ -160,6 +160,10 @@
   return CalculateNavigationControls(frame_);
 }
 
+ScreenSpanning MediaValuesDynamic::GetScreenSpanning() const {
+  return CalculateScreenSpanning(frame_);
+}
+
 Document* MediaValuesDynamic::GetDocument() const {
   return frame_->GetDocument();
 }
diff --git a/third_party/blink/renderer/core/css/media_values_dynamic.h b/third_party/blink/renderer/core/css/media_values_dynamic.h
index 779a9fb..cc1c0f2f 100644
--- a/third_party/blink/renderer/core/css/media_values_dynamic.h
+++ b/third_party/blink/renderer/core/css/media_values_dynamic.h
@@ -52,6 +52,7 @@
   bool PrefersReducedMotion() const override;
   ForcedColors GetForcedColors() const override;
   NavigationControls GetNavigationControls() const override;
+  ScreenSpanning GetScreenSpanning() const override;
   Document* GetDocument() const override;
   bool HasValues() const override;
   void OverrideViewportDimensions(double width, double height) override;
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index 1416512..a985a58 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -1305,8 +1305,11 @@
                                  match_result, state.Style(),
                                  EInsideLink::kNotInsideLink);
   collector.SetMode(SelectorChecker::kCollectingCSSRules);
-  CollectPseudoRulesForElement(*element, collector, pseudo_id,
-                               rules_to_include);
+  // TODO(obrufau): support collecting rules for nested ::marker
+  if (!element->IsPseudoElement()) {
+    CollectPseudoRulesForElement(*element, collector, pseudo_id,
+                                 rules_to_include);
+  }
 
   if (tracker_)
     AddMatchedRulesToTracker(collector);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
index 66f4604..bb8fab06 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
@@ -436,7 +436,6 @@
 }
 
 void NGFragmentItem::SetDeltaToNextForSameLayoutObject(wtf_size_t delta) const {
-  DCHECK_NE(delta, 0u);
   delta_to_next_for_same_layout_object_ = delta;
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
index ecd036d..0f61428 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.cc
@@ -66,14 +66,19 @@
            items_.begin() + 1, items_.end())) {
     if (!ShouldAssociateWithLayoutObject(*item)) {
       // These items are not associated and that no need to clear.
+      DCHECK_EQ(item->DeltaToNextForSameLayoutObject(), 0u);
       continue;
     }
     LayoutObject* object = item->GetMutableLayoutObject();
-    if (!object || object == last_object)
-      continue;
-    if (object->IsInLayoutNGInlineFormattingContext())
-      object->ClearFirstInlineFragmentItemIndex();
-    last_object = object;
+    if (object && object != last_object) {
+      if (object->IsInLayoutNGInlineFormattingContext())
+        object->ClearFirstInlineFragmentItemIndex();
+      last_object = object;
+    }
+
+    // Clear |DeltaToNextForSameLayoutObject| in case this |item| is re-used.
+    // This must be after |ClearFirstInlineFragmentItemIndex|.
+    item->SetDeltaToNextForSameLayoutObject(0u);
   }
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
index 47f688fc..2c132e1 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h"
 
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
 
@@ -147,6 +148,48 @@
   offsets_.push_back(offset);
 }
 
+void NGFragmentItemsBuilder::AddItems(const NGFragmentItems& items,
+                                      WritingMode writing_mode,
+                                      TextDirection direction,
+                                      const PhysicalSize& container_size) {
+  DCHECK(items_.IsEmpty());
+  items_.AppendVector(items.Items());
+
+  // Convert offsets to logical. The logic is opposite to |ConvertToPhysical|.
+  // This is needed because the container size may be different, in that case,
+  // the physical offsets are different when `writing-mode: vertial-rl`.
+  DCHECK(!is_converted_to_physical_);
+  DCHECK(offsets_.IsEmpty());
+  offsets_.ReserveCapacity(items.Items().size());
+  const WritingMode line_writing_mode = ToLineWritingMode(writing_mode);
+  for (NGInlineCursor cursor(items); cursor;) {
+    DCHECK(cursor.Current().Item());
+    const NGFragmentItem& item = *cursor.Current().Item();
+    offsets_.push_back(item.OffsetInContainerBlock().ConvertToLogical(
+        writing_mode, direction, container_size, item.Size()));
+
+    if (item.Type() == NGFragmentItem::kLine) {
+      const PhysicalRect line_box_bounds = item.RectInContainerBlock();
+      for (NGInlineCursor line_children = cursor.CursorForDescendants();
+           line_children; line_children.MoveToNext()) {
+        const NGFragmentItem& line_child = *line_children.Current().Item();
+        offsets_.push_back(
+            (line_child.OffsetInContainerBlock() - line_box_bounds.offset)
+                .ConvertToLogical(line_writing_mode, TextDirection::kLtr,
+                                  line_box_bounds.size, line_child.Size()));
+      }
+      cursor.MoveToNextSkippingChildren();
+      continue;
+    }
+
+    cursor.MoveToNext();
+  }
+
+  DCHECK(!text_content_);
+  text_content_ = items.Text(false);
+  first_line_text_content_ = items.Text(true);
+}
+
 const Vector<scoped_refptr<NGFragmentItem>>& NGFragmentItemsBuilder::Items(
     WritingMode writing_mode,
     TextDirection direction,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
index aed35ba..b12b8c1 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
@@ -59,6 +59,12 @@
   void AddListMarker(const NGPhysicalBoxFragment& marker_fragment,
                      const LogicalOffset& offset);
 
+  // Add previously laid out |NGFragmentItems|.
+  void AddItems(const NGFragmentItems& items,
+                WritingMode writing_mode,
+                TextDirection direction,
+                const PhysicalSize& container_size);
+
   // Find |LogicalOffset| of the first |NGFragmentItem| for |LayoutObject|.
   base::Optional<LogicalOffset> LogicalOffsetFor(const LayoutObject&) const;
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index 48c2e713..50a36329 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -427,9 +427,6 @@
   // TODO(crbug.com/992953): Add a simplified layout pass for custom layout.
   if (cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout &&
       block_flow && !GetFlowThread(block_flow) &&
-      // TODO(kojii): Enable simplified layout for fragment items.
-      !(block_flow->ChildrenInline() &&
-        RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) &&
       !block_flow->IsLayoutNGCustom()) {
     DCHECK(layout_result);
 #if DCHECK_IS_ON()
@@ -1393,8 +1390,14 @@
 
 scoped_refptr<const NGLayoutResult> NGBlockNode::RunSimplifiedLayout(
     const NGLayoutAlgorithmParams& params,
-    const NGLayoutResult& result) const {
-  return NGSimplifiedLayoutAlgorithm(params, result).Layout();
+    const NGLayoutResult& previous_result) const {
+  NGSimplifiedLayoutAlgorithm algorithm(params, previous_result);
+  if (const auto* previous_box_fragment = DynamicTo<NGPhysicalBoxFragment>(
+          &previous_result.PhysicalFragment())) {
+    if (previous_box_fragment->HasItems())
+      return algorithm.LayoutWithItemsBuilder();
+  }
+  return algorithm.Layout();
 }
 
 void NGBlockNode::CopyBaselinesFromLegacyLayout(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
index 219acd8..ce6135ca 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
@@ -625,15 +625,16 @@
             content_size_suggestion = MinMaxSizesFunc().min_size;
           } else {
             LayoutUnit intrinsic_block_size;
-            if (child.HasAspectRatio()) {
+            if (child.IsReplaced()) {
               base::Optional<LayoutUnit> computed_inline_size;
               base::Optional<LayoutUnit> computed_block_size;
               child.IntrinsicSize(&computed_inline_size, &computed_block_size);
 
-              // The 150 is for elements that have an aspect ratio but no size,
-              // which SVG can have (maybe others?).
+              // The 150 is for replaced elements that have no size, which SVG
+              // can have (maybe others?).
               intrinsic_block_size =
-                  computed_block_size.value_or(LayoutUnit(150));
+                  computed_block_size.value_or(LayoutUnit(150)) +
+                  border_padding_in_child_writing_mode.BlockSum();
             } else {
               intrinsic_block_size = IntrinsicBlockSizeFunc();
             }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
index a2bec293..2b69d7b 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
@@ -138,6 +138,22 @@
         AddChildFragment(*it, *To<NGPhysicalContainerFragment>(it->get()));
         ++it;
       }
+      if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())
+        continue;
+      // We add both items and LineBox fragments for existing mechanisms to
+      // work. We may revisit this in future. See also
+      // |NGBoxFragmentBuilder::AddResult|.
+      DCHECK(container_builder_.ItemsBuilder());
+      const NGPhysicalBoxFragment& previous_box_fragment =
+          To<NGPhysicalBoxFragment>(previous_result_.PhysicalFragment());
+      if (const NGFragmentItems* previous_items =
+              previous_box_fragment.Items()) {
+        container_builder_.ItemsBuilder()->AddItems(
+            *previous_items, writing_mode_, direction_,
+            previous_physical_container_size_);
+        continue;
+      }
+      NOTREACHED();
       continue;
     }
 
@@ -207,6 +223,18 @@
   container_builder_.AddOutOfFlowChildCandidate(child, static_offset);
 }
 
+NOINLINE scoped_refptr<const NGLayoutResult>
+NGSimplifiedLayoutAlgorithm::LayoutWithItemsBuilder() {
+  NGFragmentItemsBuilder items_builder(&container_builder_);
+  container_builder_.SetItemsBuilder(&items_builder);
+  scoped_refptr<const NGLayoutResult> result = Layout();
+  // Ensure stack-allocated |NGFragmentItemsBuilder| is not used anymore.
+  // TODO(kojii): Revisit when the storage of |NGFragmentItemsBuilder| is
+  // finalized.
+  container_builder_.SetItemsBuilder(nullptr);
+  return result;
+}
+
 void NGSimplifiedLayoutAlgorithm::AddChildFragment(
     const NGLink& old_fragment,
     const NGPhysicalContainerFragment& new_fragment) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
index 6921bc3e..ddb9c438 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
@@ -44,6 +44,8 @@
 
   scoped_refptr<const NGLayoutResult> Layout() override;
 
+  NOINLINE scoped_refptr<const NGLayoutResult> LayoutWithItemsBuilder();
+
  private:
   void HandleOutOfFlowPositioned(const NGBlockNode&);
 
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.cc b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.cc
index 3b7d06f..3c46c9d 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.cc
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.cc
@@ -10,6 +10,7 @@
 #include "services/metrics/public/cpp/ukm_recorder.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_media_key_system_media_capability.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/modules/encryptedmedia/encrypted_media_utils.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
@@ -133,7 +134,7 @@
     supported_configurations_[i] = web_config;
   }
 
-  CheckVideoCapabilityRobustness();
+  GenerateWarningAndReportMetrics();
 }
 
 const SecurityOrigin* MediaKeySystemAccessInitializerBase::GetSecurityOrigin()
@@ -160,7 +161,7 @@
   return context && !context->IsContextDestroyed();
 }
 
-void MediaKeySystemAccessInitializerBase::CheckVideoCapabilityRobustness()
+void MediaKeySystemAccessInitializerBase::GenerateWarningAndReportMetrics()
     const {
   const char kWidevineKeySystem[] = "com.widevine.alpha";
   const char kWidevineHwSecureAllRobustness[] = "HW_SECURE_ALL";
@@ -219,13 +220,18 @@
   if (!IsExecutionContextValid())
     return;
 
-  Document* document = Document::From(GetExecutionContext());
-  if (!document)
+  Document* document = GetDocument();
+  LocalFrame* frame = GetFrame();
+  if (!document || !frame)
     return;
 
   ukm::builders::Media_EME_RequestMediaKeySystemAccess builder(
       document->UkmSourceID());
   builder.SetKeySystem(KeySystemForUkm::kWidevine);
+  builder.SetIsAdFrame(
+      static_cast<int>(frame->IsAdRoot() || frame->IsAdSubframe()));
+  builder.SetIsCrossOrigin(static_cast<int>(frame->IsCrossOriginToMainFrame()));
+  builder.SetIsTopFrame(static_cast<int>(frame->IsMainFrame()));
   builder.SetVideoCapabilities(static_cast<int>(has_video_capabilities));
   builder.SetVideoCapabilities_HasEmptyRobustness(
       static_cast<int>(has_empty_robustness));
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.h b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.h
index aec82d3..7dec312 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.h
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.h
@@ -47,10 +47,10 @@
   // Returns true if the ExecutionContext is valid, false otherwise.
   bool IsExecutionContextValid() const;
 
-  // For widevine key system, generate warning and report to UMA if
-  // |m_supportedConfigurations| contains any video capability with empty
-  // robustness string.
-  void CheckVideoCapabilityRobustness() const;
+  // For widevine key system, generate warning if |supported_configurations_|
+  // contains any video capability with empty robustness string. Also report
+  // UMA and UKM.
+  void GenerateWarningAndReportMetrics() const;
 
   Member<ScriptPromiseResolver> resolver_;
   const String key_system_;
diff --git a/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc b/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc
index 649ed30..8de5bdd 100644
--- a/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc
+++ b/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc
@@ -13,17 +13,14 @@
 
 // SensorProviderProxy
 SensorProviderProxy::SensorProviderProxy(Document& document)
-    : Supplement<Document>(document),
-      sensor_provider_(document.ToExecutionContext()),
-      inspector_mode_(false) {}
+    : Supplement<Document>(document), inspector_mode_(false) {}
 
 void SensorProviderProxy::InitializeIfNeeded() {
   if (IsInitialized())
     return;
 
   GetSupplementable()->GetBrowserInterfaceBroker().GetInterface(
-      sensor_provider_.BindNewPipeAndPassReceiver(
-          GetSupplementable()->GetTaskRunner(TaskType::kSensor)));
+      sensor_provider_.BindNewPipeAndPassReceiver());
   sensor_provider_.set_disconnect_handler(
       WTF::Bind(&SensorProviderProxy::OnSensorProviderConnectionError,
                 WrapWeakPersistent(this)));
@@ -49,7 +46,6 @@
 
 void SensorProviderProxy::Trace(Visitor* visitor) {
   visitor->Trace(sensor_proxies_);
-  visitor->Trace(sensor_provider_);
   Supplement<Document>::Trace(visitor);
 }
 
diff --git a/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h b/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h
index 46616c3a..e356f73 100644
--- a/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h
+++ b/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h
@@ -6,13 +6,12 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_SENSOR_SENSOR_PROVIDER_PROXY_H_
 
 #include "base/macros.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/sensor.mojom-blink-forward.h"
 #include "services/device/public/mojom/sensor_provider.mojom-blink.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
 
 namespace blink {
@@ -59,9 +58,7 @@
   void OnSensorProviderConnectionError();
   SensorsSet sensor_proxies_;
 
-  HeapMojoRemote<device::mojom::blink::SensorProvider,
-                 HeapMojoWrapperMode::kWithoutContextObserver>
-      sensor_provider_;
+  mojo::Remote<device::mojom::blink::SensorProvider> sensor_provider_;
   bool inspector_mode_;
 
   DISALLOW_COPY_AND_ASSIGN(SensorProviderProxy);
diff --git a/third_party/blink/renderer/modules/webtransport/quic_transport.cc b/third_party/blink/renderer/modules/webtransport/quic_transport.cc
index bb5f950..a645317 100644
--- a/third_party/blink/renderer/modules/webtransport/quic_transport.cc
+++ b/third_party/blink/renderer/modules/webtransport/quic_transport.cc
@@ -101,7 +101,7 @@
 
  private:
   ScriptPromise SendDatagram(base::span<const uint8_t> data) {
-    if (!quic_transport_->quic_transport_) {
+    if (!quic_transport_->quic_transport_.is_bound()) {
       // Silently drop the datagram if we are not connected.
       // TODO(ricea): Change the behaviour if the standard changes. See
       // https://github.com/WICG/web-transport/issues/93.
@@ -242,15 +242,23 @@
 QuicTransport::QuicTransport(PassKey,
                              ScriptState* script_state,
                              const String& url)
-    : ExecutionContextLifecycleObserver(ExecutionContext::From(script_state)),
+    : QuicTransport(script_state, url, ExecutionContext::From(script_state)) {}
+
+QuicTransport::QuicTransport(ScriptState* script_state,
+                             const String& url,
+                             ExecutionContext* context)
+    : ExecutionContextLifecycleObserver(context),
       script_state_(script_state),
-      url_(NullURL(), url) {}
+      url_(NullURL(), url),
+      quic_transport_(context),
+      handshake_client_receiver_(this, context),
+      client_receiver_(this, context) {}
 
 ScriptPromise QuicTransport::createSendStream(ScriptState* script_state,
                                               ExceptionState& exception_state) {
   DVLOG(1) << "QuicTransport::createSendStream() this=" << this;
 
-  if (!quic_transport_) {
+  if (!quic_transport_.is_bound()) {
     // TODO(ricea): Should we wait if we're still connecting?
     exception_state.ThrowDOMException(DOMExceptionCode::kNetworkError,
                                       "No connection.");
@@ -335,7 +343,7 @@
   client_receiver_.set_disconnect_handler(
       WTF::Bind(&QuicTransport::OnConnectionError, WrapWeakPersistent(this)));
 
-  DCHECK(!quic_transport_);
+  DCHECK(!quic_transport_.is_bound());
   quic_transport_.Bind(std::move(quic_transport), task_runner);
 
   received_streams_underlying_source_->NotifyOpened();
@@ -411,6 +419,9 @@
   visitor->Trace(outgoing_datagrams_);
   visitor->Trace(script_state_);
   visitor->Trace(create_send_stream_resolvers_);
+  visitor->Trace(quic_transport_);
+  visitor->Trace(handshake_client_receiver_);
+  visitor->Trace(client_receiver_);
   visitor->Trace(ready_resolver_);
   visitor->Trace(ready_);
   visitor->Trace(closed_resolver_);
diff --git a/third_party/blink/renderer/modules/webtransport/quic_transport.h b/third_party/blink/renderer/modules/webtransport/quic_transport.h
index c562fab..5e88fca 100644
--- a/third_party/blink/renderer/modules/webtransport/quic_transport.h
+++ b/third_party/blink/renderer/modules/webtransport/quic_transport.h
@@ -11,8 +11,6 @@
 #include "base/util/type_safety/pass_key.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "services/network/public/mojom/quic_transport.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
@@ -21,6 +19,8 @@
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 
@@ -98,6 +98,8 @@
   class DatagramUnderlyingSource;
   class ReceivedStreamsUnderlyingSource;
 
+  QuicTransport(ScriptState*, const String& url, ExecutionContext* context);
+
   void Init(const String& url, ExceptionState&);
 
   // Reset the QuicTransport object and all associated streams.
@@ -132,11 +134,12 @@
               WTF::UnsignedWithZeroKeyHashTraits<uint32_t>>
       stream_map_;
 
-  mojo::Remote<network::mojom::blink::QuicTransport> quic_transport_;
-  mojo::Receiver<network::mojom::blink::QuicTransportHandshakeClient>
-      handshake_client_receiver_{this};
-  mojo::Receiver<network::mojom::blink::QuicTransportClient> client_receiver_{
-      this};
+  HeapMojoRemote<network::mojom::blink::QuicTransport> quic_transport_;
+  HeapMojoReceiver<network::mojom::blink::QuicTransportHandshakeClient,
+                   QuicTransport>
+      handshake_client_receiver_;
+  HeapMojoReceiver<network::mojom::blink::QuicTransportClient, QuicTransport>
+      client_receiver_;
   Member<ScriptPromiseResolver> ready_resolver_;
   ScriptPromise ready_;
   Member<ScriptPromiseResolver> closed_resolver_;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 7dcd1a1..cbd87d6 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -412,6 +412,9 @@
       status: "experimental",
     },
     {
+      name: "CSSFoldables",
+    },
+    {
       name: "CSSFontSizeAdjust",
       status: "experimental",
     },
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py b/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
index a5d8b07..2f53dd1 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
@@ -311,9 +311,18 @@
             port, worker_number, no_timeout)
 
     def _base_cmd_line(self):
-        return ['run',
-                'fuchsia-pkg://fuchsia.com/content_shell#meta/content_shell.cmx',
-                '--ozone-platform=headless']
+        cmd = ['run', 'fuchsia-pkg://fuchsia.com/content_shell#meta/content_shell.cmx']
+        if self._port._target_device == 'qemu':
+            cmd.append('--ozone-platform=headless')
+        # Use Scenic on AEMU
+        elif self._port._target_device == 'aemu':
+            cmd.extend([
+                '--ozone-platform=scenic',
+                '--enable-oop-rasterization',
+                '--use-gl=stub',
+                '--enable-features=UseSkiaRenderer,Vulkan'
+            ])
+        return cmd
 
     def _command_from_driver_input(self, driver_input):
         command = super(ChromiumFuchsiaDriver, self)._command_from_driver_input(
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 22b24d63..b92cac0 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -91,7 +91,6 @@
 # Tests temporarily disabled with Site Isolation - test issues or test harness
 # issues (e.g. missing OOPIF support in the test harness).
 # TODO(lukasza, alexmos): Burn down this list.
-crbug.com/665058 http/tests/local/drag-over-remote-content.html [ Crash Timeout ]
 crbug.com/771003 http/tests/security/mixedContent/insecure-iframe-in-main-frame.html [ Failure ]
 
 crbug.com/1050826 external/wpt/mixed-content/gen/top.http-rp/opt-in/object-tag.https.html [ Timeout ]
@@ -876,22 +875,6 @@
 crbug.com/591099 [ Win ] virtual/text-antialias/international/shape-across-elements-simple.html [ Failure ]
 crbug.com/591099 [ Mac ] virtual/text-antialias/word-space-monospace.html [ Failure ]
 crbug.com/591099 [ Win ] virtual/text-antialias/word-space-monospace.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] fast/block/float/float-in-float-painting.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] fast/css/clip-zooming.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] fast/css/nth-child-dynamic.html [ Failure Timeout ]
-crbug.com/591099 [ Fuchsia ] fast/css/text-overflow-ellipsis-strict.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] fast/css/text-overflow-ellipsis.html [ Failure Timeout ]
-crbug.com/591099 [ Fuchsia ] fast/inline/inline-box-background-repeat-x.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] fast/inline/inline-box-background-repeat-y.html [ Failure Timeout ]
-crbug.com/591099 [ Fuchsia ] fast/inline/inline-box-background.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] fast/layers/opacity-transforms.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] fast/lists/003.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] fast/lists/scrolled-marker-paint.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] virtual/text-antialias/international/bidi-LDB-2-HTML.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] virtual/text-antialias/international/bidi-LDB-2-formatting-characters.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] virtual/text-antialias/international/bidi-neutral-directionality-paragraph-start.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] tables/mozilla_expected_failures/bugs/bug1010.html [ Failure ]
-crbug.com/591099 [ Fuchsia ] tables/mozilla_expected_failures/bugs/bug1055-2.html [ Failure ]
 crbug.com/591099 [ Mac ] css2.1/t1202-counter-09-b.html [ Failure ]
 crbug.com/591099 [ Mac ] css2.1/t1202-counters-09-b.html [ Failure ]
 crbug.com/591099 [ Mac ] external/wpt/css/CSS2/text/white-space-bidirectionality-001.xht [ Failure ]
@@ -1979,10 +1962,8 @@
 
 # gpuBenchmarking.pinchBy is busted on desktops for touchscreen pinch
 crbug.com/787615 [ Win ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-in-slow.html [ Failure Pass ]
-crbug.com/787615 [ Fuchsia ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-in-slow.html [ Failure Pass ]
 crbug.com/787615 [ Win ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen.html [ Failure Pass ]
 crbug.com/787615 [ Linux ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen.html [ Failure Pass ]
-crbug.com/787615 [ Fuchsia ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen.html [ Failure Pass ]
 
 # Flakily fail on Linux Tests (dbg) and Win7.
 crbug.com/953725 [ Win ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchpad-zoom-in-slow.html [ Failure Pass ]
@@ -2153,7 +2134,7 @@
 crbug.com/123456 [ Mac ] virtual/form-controls-refresh-disabled/fast/forms/select/menulist-onchange-fired-with-key-up-down.html [ Skip ]
 crbug.com/123456 [ Mac ] virtual/form-controls-refresh-disabled/fast/forms/select/popup-with-display-none-optgroup.html [ Skip ]
 
-crbug.com/1056027 [ Fuchsia ] virtual/text-antialias/small-caps-aat.html [ Failure Pass ]
+crbug.com/1056027 [ Fuchsia ] virtual/text-antialias/small-caps-aat.html [ Failure Pass Timeout ]
 crbug.com/1057339 [ Fuchsia ] virtual/text-antialias/international/rtl-mark.html [ Failure Pass ]
 
 # `hyphens: auto` not supported on Win/Linux/ChromeOS
@@ -3152,6 +3133,9 @@
 crbug.com/1067277 external/wpt/css/css-content/element-replacement-on-replaced-element.tentative.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Linux ] external/wpt/css/css-pseudo/active-selection-063.html [ Failure ]
+crbug.com/626703 [ Mac ] external/wpt/css/css-pseudo/active-selection-063.html [ Failure ]
+crbug.com/626703 [ Win ] external/wpt/css/css-pseudo/active-selection-063.html [ Failure ]
 crbug.com/626703 [ Mac10.14 ] external/wpt/preload/onload-event.html [ Timeout ]
 crbug.com/626703 [ Mac10.10 ] external/wpt/storage/estimate-indexeddb.https.any.worker.html [ Failure Timeout ]
 crbug.com/626703 [ Mac10.10 ] external/wpt/fetch/origin/assorted.window.html [ Failure Timeout ]
@@ -5033,6 +5017,118 @@
 crbug.com/919639 [ Fuchsia ] presentation/presentationconnectionavailableevent-ctor-mock.html [ Failure ]
 crbug.com/919639 [ Fuchsia ] webmidi/permission.html [ Failure ]
 
+# These tests timeout when using Scenic ozone platform.
+crbug.com/1067477 [ Fuchsia ] compositing/sibling-positioning.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] css3/selectors3/html/css3-modsel-18.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] css3/selectors3/html/css3-modsel-61.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] css3/selectors3/xhtml/css3-modsel-17.xml [ Skip ]
+crbug.com/1067477 [ Fuchsia ] css3/selectors3/xhtml/css3-modsel-18.xml [ Skip ]
+crbug.com/1067477 [ Fuchsia ] css3/selectors3/xml/css3-modsel-17.xml [ Skip ]
+crbug.com/1067477 [ Fuchsia ] css3/selectors3/xml/css3-modsel-18.xml [ Skip ]
+crbug.com/1067477 [ Fuchsia ] css3/selectors3/xml/css3-modsel-61.xml [ Skip ]
+crbug.com/1067477 [ Fuchsia ] editing/execCommand/5190926.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] editing/pasteboard/paste-line-endings-001.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] editing/pasteboard/paste-line-endings-002.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] editing/pasteboard/paste-line-endings-003.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] editing/pasteboard/paste-line-endings-004.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] editing/pasteboard/paste-line-endings-005.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] editing/selection/4402375.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] editing/selection/6476.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] editing/selection/leave-requested-block.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] editing/selection/previous-line-position.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] editing/style/block-styles-007.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] external/wpt/bluetooth/requestDevice/canonicalizeFilter/no-arguments.https.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/backgrounds/background-clip-text.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/block/basic/018.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/block/float/002.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/block/float/centered-float-avoidance-complexity.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/block/float/float-in-float-hit-testing.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/block/float/float-in-float-painting.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/block/margin-collapse/019.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/block/margin-collapse/020.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/block/margin-collapse/block-inside-inline/019.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/block/margin-collapse/block-inside-inline/020.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/child-style-can-override-visited-style.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/clip-zooming.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/compare-content-style.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/first-letter-hover.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/first-letter-visibility.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/focus-ring-multiline.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/font-face-default-font.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/invalid-percentage-property.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/line-height-font-order.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/line-thickness-underline-strikethrough-overline.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/nth-child-dynamic.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/text-overflow-ellipsis-strict.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css/text-overflow-ellipsis.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css3-text/css3-text-decoration/text-decoration-style-inherit.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/css3-text/css3-text-decoration/text-decoration-style.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/events/reveal-link-when-focused.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/events/wheel/wheelevent-in-text-node.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/forms/date/date-chooseronly-defaultValue.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/hidpi/clip-text-in-hidpi.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/inline-block/14498-positionForCoordinates.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/inline-block/overflow-clip.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/inline/inline-box-background-repeat-x.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/inline/inline-box-background-repeat-y.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/inline/inline-box-background.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/inline/inline-focus-ring.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/invalid/009.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/layers/normal-flow-hit-test.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/layers/opacity-transforms.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/lists/003.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/lists/scrolled-marker-paint.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/media/matchmedium-query-api.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/overflow/position-fixed-transform-clipping.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/replaced/image-map-2.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/replaced/selection-rect-transform.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/selectors/018.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/selectors/061.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/table/border-collapsing/004.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] fast/writing-mode/english-lr-text.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] images/imagemap-focus-ring-outline-color-not-inherited-from-map.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] paint/invalidation/button-inner-no-repaint.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] paint/invalidation/compositing/should-not-repaint-composited-opacity.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] paint/invalidation/outline/focus-layers.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] paint/invalidation/selection/selected-replaced.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] paint/invalidation/selection/selection-in-composited-scrolling-container.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] paint/invalidation/shadow-multiple.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] svg/as-background-image/svg-width-100p-as-background.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] svg/batik/text/textAnchor3.svg [ Skip ]
+crbug.com/1067477 [ Fuchsia ] synthetic_gestures/smooth-scroll-tiny-delta.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/hittesting/filltable-levels.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/mozilla/bugs/bug1188.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/mozilla/bugs/bug2479-3.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/mozilla/bugs/bug2479-4.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/mozilla/bugs/bug59354.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/mozilla/bugs/bug7342.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/mozilla/bugs/bug8950.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/mozilla/collapsing_borders/bug41262-3.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/mozilla/core/bloomberg.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/mozilla_expected_failures/bugs/bug1010.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/mozilla_expected_failures/bugs/bug1055-2.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] tables/mozilla_expected_failures/bugs/bug2479-5.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] transforms/transformed-caret.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] virtual/text-antialias/international/003.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] virtual/text-antialias/international/bidi-LDB-2-HTML.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] virtual/text-antialias/international/bidi-LDB-2-formatting-characters.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] virtual/text-antialias/international/bidi-neutral-directionality-paragraph-start.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] virtual/text-antialias/stroking-decorations.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] virtual/threaded/synthetic_gestures/smooth-scroll-tiny-delta.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-in-slow.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-out-slow.html [ Skip ]
+crbug.com/1067477 [ Fuchsia ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen.html [ Skip ]
+
+# These tests are flaky when using Scenic ozone platform.
+crbug.com/1047480 [ Fuchsia ] css3/calc/reflection-computed-style.html [ Failure Pass ]
+crbug.com/1047480 [ Fuchsia ] external/wpt/web-animations/interfaces/Animation/ready.html [ Failure Pass ]
+crbug.com/1047480 [ Fuchsia ] fast/block/float/floats-with-margin-should-not-wrap.html [ Failure Pass ]
+crbug.com/1047480 [ Fuchsia ] fast/block/margin-collapse/clear-nested-float-more-than-one-previous-sibling-away.html [ Failure Pass ]
+crbug.com/1047480 [ Fuchsia ] virtual/gpu-rasterization/images/drag-image-descendant-painting-sibling.html [ Failure Pass ]
+
 ### See crbug.com/891427 comment near the top of this file:
 ###crbug.com/816914 [ Mac ] fast/canvas/canvas-drawImage-live-video.html [ Failure Pass ]
 crbug.com/817167 http/tests/devtools/oopif/oopif-cookies-refresh.js [ Failure Timeout Pass ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index b732c40..46ba3c7333 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -460,7 +460,6 @@
               "http/tests/inspector-protocol/request-mixed-content-status-none.js",
               "http/tests/inspector-protocol/request-mixed-content-status-optionally-blockable.js",
               "http/tests/loading/bad-server-subframe.html",
-              "http/tests/local/drag-over-remote-content.html",
               "http/tests/media/autoplay/document-user-activation-feature-policy-iframe-no-gesture.html",
               "http/tests/media/autoplay/webaudio-autoplay-iframe-with-gesture.html",
               "http/tests/misc/iframe-script-modify-attr.html",
diff --git a/third_party/blink/web_tests/css3/flexbox/orthogonal-writing-modes-and-intrinsic-sizing.html b/third_party/blink/web_tests/css3/flexbox/orthogonal-writing-modes-and-intrinsic-sizing.html
deleted file mode 100644
index 567d49d..0000000
--- a/third_party/blink/web_tests/css3/flexbox/orthogonal-writing-modes-and-intrinsic-sizing.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<html>
-<link href="resources/flexbox.css" rel="stylesheet">
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/check-layout-th.js"></script>
-
-<style>
-.flexbox {
-    background-color: gray;
-}
-
-.vertical {
-    writing-mode: vertical-lr;
-    width: min-content;
-    background-color: blue;
-}
-</style>
-<body onload="checkLayout('.flexbox')">
-<div id=log></div>
-
-<div class="flexbox" data-expected-height="20">
-    <div class="vertical" data-expected-width="50" data-expected-height="20">
-        <div style="width: 50px; height: 20px; background-color: blue;" data-expected-width="50" data-expected-height="20"></div>
-    </div>
-</div>
-
-
-<div class="flexbox column" data-expected-height="20">
-    <div class="vertical" data-expected-width="50" data-expected-height="20">
-        <div style="width: 50px; height: 20px; background-color: blue;" data-expected-width="50" data-expected-height="20"></div>
-    </div>
-</div>
diff --git a/third_party/blink/web_tests/css3/flexbox/relpos-with-percentage-top.html b/third_party/blink/web_tests/css3/flexbox/relpos-with-percentage-top.html
deleted file mode 100644
index 72e5fa3..0000000
--- a/third_party/blink/web_tests/css3/flexbox/relpos-with-percentage-top.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<style>
-html, body {
-  margin: 0;
-}
-
-.border {
-  border:1px solid #000;
-}
-.width-50 {
-  width: 50%;
-}
-.flex {
-  display: flex;
-  flex-flow: row wrap;
-}
-.tall {
-  height: 300px;
-}
-.top-50 {
-  position: relative;
-  top: 50%;
-}
-</style>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/check-layout-th.js"></script>
-<body onload="checkLayout('.border')">
-<div class="border">
-  <div class="flex">
-    <div class="width-50">
-      <label class="top-50" data-offset-y="151">This should be in the center of the container</label>
-    </div>
-    <div class="width-50">
-      <div class="tall">
-        This is tall
-      </div>
-    </div>
-  </div>
-</div>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
index 822f820..3122f6f5 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
@@ -68117,6 +68117,18 @@
      {}
     ]
    ],
+   "css/css-pseudo/active-selection-063.html": [
+    [
+     "css/css-pseudo/active-selection-063.html",
+     [
+      [
+       "/css/css-pseudo/reference/ref-filled-green-100px-square.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-pseudo/before-dynamic-display-none.html": [
     [
      "css/css-pseudo/before-dynamic-display-none.html",
@@ -108527,6 +108539,30 @@
      {}
     ]
    ],
+   "css/filter-effects/effect-reference-feimage-001.html": [
+    [
+     "css/filter-effects/effect-reference-feimage-001.html",
+     [
+      [
+       "/css/filter-effects/reference/effect-reference-feimage-001-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/filter-effects/effect-reference-feimage-002.html": [
+    [
+     "css/filter-effects/effect-reference-feimage-002.html",
+     [
+      [
+       "/css/filter-effects/reference/effect-reference-feimage-002-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/filter-effects/effect-reference-lighting-no-light.tentative.html": [
     [
      "css/filter-effects/effect-reference-lighting-no-light.tentative.html",
@@ -108551,6 +108587,30 @@
      {}
     ]
    ],
+   "css/filter-effects/effect-reference-obb-dimensions.html": [
+    [
+     "css/filter-effects/effect-reference-obb-dimensions.html",
+     [
+      [
+       "/css/filter-effects/reference/effect-reference-obb-dimensions-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/filter-effects/effect-reference-on-span.html": [
+    [
+     "css/filter-effects/effect-reference-on-span.html",
+     [
+      [
+       "/css/filter-effects/reference/effect-reference-on-span-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/filter-effects/effect-reference-rename-001.html": [
     [
      "css/filter-effects/effect-reference-rename-001.html",
@@ -108563,6 +108623,18 @@
      {}
     ]
    ],
+   "css/filter-effects/effect-reference-rename-002.html": [
+    [
+     "css/filter-effects/effect-reference-rename-002.html",
+     [
+      [
+       "/css/filter-effects/reference/effect-reference-rename-002-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/filter-effects/empty-element-with-filter.html": [
     [
      "css/filter-effects/empty-element-with-filter.html",
@@ -109031,6 +109103,18 @@
      {}
     ]
    ],
+   "css/filter-effects/root-element-with-opacity-filter-001.html": [
+    [
+     "css/filter-effects/root-element-with-opacity-filter-001.html",
+     [
+      [
+       "/css/filter-effects/reference/root-element-with-opacity-filter-001-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/filter-effects/svg-feflood-001.html": [
     [
      "css/filter-effects/svg-feflood-001.html",
@@ -135257,6 +135341,12 @@
    "content-dpr/tiled-background-svg-image-with-content-dpr-ref.html": [
     []
    ],
+   "content-index/resources.js": [
+    []
+   ],
+   "content-index/resources/sw.js": [
+    []
+   ],
    "content-security-policy/META.yml": [
     []
    ],
@@ -151649,6 +151739,9 @@
    "css/css-pseudo/placeholder-input-number-notref.html": [
     []
    ],
+   "css/css-pseudo/reference/ref-filled-green-100px-square.xht": [
+    []
+   ],
    "css/css-pseudo/selection-text-shadow-016-ref.html": [
     []
    ],
@@ -159992,15 +160085,30 @@
    "css/filter-effects/reference/effect-reference-delete-ref.html": [
     []
    ],
+   "css/filter-effects/reference/effect-reference-feimage-001-ref.html": [
+    []
+   ],
+   "css/filter-effects/reference/effect-reference-feimage-002-ref.html": [
+    []
+   ],
    "css/filter-effects/reference/effect-reference-lighting-no-light.tentative-ref.html": [
     []
    ],
    "css/filter-effects/reference/effect-reference-merge-no-inputs.tentative-ref.html": [
     []
    ],
+   "css/filter-effects/reference/effect-reference-obb-dimensions-ref.html": [
+    []
+   ],
+   "css/filter-effects/reference/effect-reference-on-span-ref.html": [
+    []
+   ],
    "css/filter-effects/reference/effect-reference-rename-001-ref.html": [
     []
    ],
+   "css/filter-effects/reference/effect-reference-rename-002-ref.html": [
+    []
+   ],
    "css/filter-effects/reference/empty-element-with-filter-ref.html": [
     []
    ],
@@ -160031,6 +160139,9 @@
    "css/filter-effects/reference/reference-filter-update-on-attribute-change-001-ref.html": [
     []
    ],
+   "css/filter-effects/reference/root-element-with-opacity-filter-001-ref.html": [
+    []
+   ],
    "css/filter-effects/reference/svg-feflood-ref.html": [
     []
    ],
@@ -186392,6 +186503,9 @@
    "touch-events/support/touch.js": [
     []
    ],
+   "trust-tokens/end-to-end/README.txt": [
+    []
+   ],
    "trusted-types/META.yml": [
     []
    ],
@@ -212282,6 +212396,23 @@
      {}
     ]
    ],
+   "content-index/content-index.https.window.js": [
+    [
+     "content-index/content-index.https.window.html",
+     {
+      "script_metadata": [
+       [
+        "script",
+        "/service-workers/service-worker/resources/test-helpers.sub.js"
+       ],
+       [
+        "script",
+        "resources.js"
+       ]
+      ]
+     }
+    ]
+   ],
    "content-security-policy/base-uri/base-uri-allow.sub.html": [
     [
      "content-security-policy/base-uri/base-uri-allow.sub.html",
@@ -215763,6 +215894,12 @@
      {}
     ]
    ],
+   "cookie-store/cookieStore_opaque_origin.tentative.https.html": [
+    [
+     "cookie-store/cookieStore_opaque_origin.tentative.https.html",
+     {}
+    ]
+   ],
    "cookie-store/cookieStore_set_arguments.tentative.https.any.js": [
     [
      "cookie-store/cookieStore_set_arguments.tentative.https.any.html",
@@ -219635,6 +219772,12 @@
      {}
     ]
    ],
+   "css/css-flexbox/abspos-descendent-001.html": [
+    [
+     "css/css-flexbox/abspos-descendent-001.html",
+     {}
+    ]
+   ],
    "css/css-flexbox/align-content-wrap-001.html": [
     [
      "css/css-flexbox/align-content-wrap-001.html",
@@ -220667,6 +220810,12 @@
      {}
     ]
    ],
+   "css/css-flexbox/position-relative-percentage-top-001.html": [
+    [
+     "css/css-flexbox/position-relative-percentage-top-001.html",
+     {}
+    ]
+   ],
    "css/css-flexbox/quirks-auto-block-size-with-percentage-item.html": [
     [
      "css/css-flexbox/quirks-auto-block-size-with-percentage-item.html",
@@ -238550,6 +238699,24 @@
      }
     ]
    ],
+   "dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html": [
+    [
+     "dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html",
+     {
+      "testdriver": true,
+      "timeout": "long"
+     }
+    ]
+   ],
+   "dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html": [
+    [
+     "dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html",
+     {
+      "testdriver": true,
+      "timeout": "long"
+     }
+    ]
+   ],
    "dom/events/scrolling/scrollend-event-fired-to-document.html": [
     [
      "dom/events/scrolling/scrollend-event-fired-to-document.html",
@@ -268078,6 +268245,24 @@
      {}
     ]
    ],
+   "html/semantics/forms/the-label-element/clicking-interactive-content.html": [
+    [
+     "html/semantics/forms/the-label-element/clicking-interactive-content.html",
+     {}
+    ]
+   ],
+   "html/semantics/forms/the-label-element/clicking-noninteractive-labelable-content.html": [
+    [
+     "html/semantics/forms/the-label-element/clicking-noninteractive-labelable-content.html",
+     {}
+    ]
+   ],
+   "html/semantics/forms/the-label-element/clicking-noninteractive-unlabelable-content.html": [
+    [
+     "html/semantics/forms/the-label-element/clicking-noninteractive-unlabelable-content.html",
+     {}
+    ]
+   ],
    "html/semantics/forms/the-label-element/forward-focus-to-associated-element.html": [
     [
      "html/semantics/forms/the-label-element/forward-focus-to-associated-element.html",
@@ -315064,6 +315249,18 @@
      {}
     ]
    ],
+   "trust-tokens/end-to-end/has-trust-token-with-no-top-frame.tentative.https.html": [
+    [
+     "trust-tokens/end-to-end/has-trust-token-with-no-top-frame.tentative.https.html",
+     {}
+    ]
+   ],
+   "trust-tokens/end-to-end/has-trust-token.tentative.https.html": [
+    [
+     "trust-tokens/end-to-end/has-trust-token.tentative.https.html",
+     {}
+    ]
+   ],
    "trust-tokens/trust-token-parameter-validation-xhr.tentative.https.html": [
     [
      "trust-tokens/trust-token-parameter-validation-xhr.tentative.https.html",
@@ -353760,6 +353957,18 @@
    "56948ea286b8c9869863e139147348056727fa20",
    "reftest"
   ],
+  "content-index/content-index.https.window.js": [
+   "082ebc3b9ec599da21351d4be1f21a79810ec65d",
+   "testharness"
+  ],
+  "content-index/resources.js": [
+   "1a758abe27e0b31dd22d2b8c04a7943271dea95c",
+   "support"
+  ],
+  "content-index/resources/sw.js": [
+   "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
+   "support"
+  ],
   "content-security-policy/META.yml": [
    "ee8f1ea7e07b94711ddc65e43a6c32dbc5983612",
    "support"
@@ -356789,7 +356998,7 @@
    "testharness"
   ],
   "cookie-store/cookieStore_get_arguments.tentative.https.any.js": [
-   "79fc0d37488ef6dfed1f0bc210e2116111acc776",
+   "34f7dbcd948fd5e590b0e9f715ad878f4de9694d",
    "testharness"
   ],
   "cookie-store/cookieStore_get_delete_basic.tentative.https.any.js": [
@@ -356816,6 +357025,10 @@
    "08a7b5b8e4629440956943489dd7fa7ca200b537",
    "testharness"
   ],
+  "cookie-store/cookieStore_opaque_origin.tentative.https.html": [
+   "bbf0dbd9864c574fadbd2b464618766ff1919a19",
+   "testharness"
+  ],
   "cookie-store/cookieStore_set_arguments.tentative.https.any.js": [
    "b9074c827d2a1ffa9b3ee1a0a28714396c4ae0d8",
    "testharness"
@@ -383204,6 +383417,10 @@
    "a156a727a529f7fbb0ba92b216d47487bc1b3125",
    "reftest"
   ],
+  "css/css-flexbox/abspos-descendent-001.html": [
+   "1aebb0f319f566db19070e7bad66e622a4ab8d3f",
+   "testharness"
+  ],
   "css/css-flexbox/align-baseline.html": [
    "31bcca69771751f3277d6f078456f982a375d067",
    "reftest"
@@ -384253,7 +384470,7 @@
    "visual"
   ],
   "css/css-flexbox/flexbox-with-multi-column-property.html": [
-   "5b11b0f9fd245a451e289229c4ed3e6e183dd40b",
+   "56b56ca0935bc8869a4b19e0d70e2cf7cdb0a0b8",
    "reftest"
   ],
   "css/css-flexbox/flexbox_absolute-atomic-ref.html": [
@@ -386784,6 +387001,10 @@
    "a3de19d6d9df95a505c547e48dea3de82af44de5",
    "reftest"
   ],
+  "css/css-flexbox/position-relative-percentage-top-001.html": [
+   "3ec47c1d42d69330c616a87f0b22208f8d6196a6",
+   "testharness"
+  ],
   "css/css-flexbox/quirks-auto-block-size-with-percentage-item.html": [
    "966f39f173952f01268dcd26a9a5892bf4a689a9",
    "testharness"
@@ -407660,6 +407881,10 @@
    "ae3222595453ec46cf48810cb2f276126897bac6",
    "support"
   ],
+  "css/css-pseudo/active-selection-063.html": [
+   "1d9a1c1ecd81008d4d3d5891b717d6bdadb3efe9",
+   "reftest"
+  ],
   "css/css-pseudo/before-dynamic-display-none.html": [
    "d8844f9c961e94b2fd353628cb2c6e3e12123054",
    "reftest"
@@ -408224,6 +408449,10 @@
    "a557f1091ec29dd90cd4290cf96ac4752b04ff3f",
    "reftest"
   ],
+  "css/css-pseudo/reference/ref-filled-green-100px-square.xht": [
+   "05a13794482a94f6c10bd9d4c98704e63ef60331",
+   "support"
+  ],
   "css/css-pseudo/selection-text-shadow-006-manual.html": [
    "57c9ad67d17bd7a3a37acd86bef43989c45d9480",
    "manual"
@@ -441296,6 +441525,14 @@
    "314c9a7d123bd65b04483956513337116f7e0382",
    "reftest"
   ],
+  "css/filter-effects/effect-reference-feimage-001.html": [
+   "3a8fb36db92fb408c7011f44724bc8457da7ff37",
+   "reftest"
+  ],
+  "css/filter-effects/effect-reference-feimage-002.html": [
+   "c10be0f173ef6638461a7475fefb9ee5f61ac578",
+   "reftest"
+  ],
   "css/filter-effects/effect-reference-lighting-no-light.tentative.html": [
    "beefd47a544d5c82b4b1d468ce99938e6d9924d9",
    "reftest"
@@ -441304,10 +441541,22 @@
    "4fb67db643dd5aebdbff53a0773035747c18836c",
    "reftest"
   ],
+  "css/filter-effects/effect-reference-obb-dimensions.html": [
+   "2bb424d90cd6b03145c481eb8be6b96c9d52d715",
+   "reftest"
+  ],
+  "css/filter-effects/effect-reference-on-span.html": [
+   "66bd8fa886a86e5f5738d8373e2611c39cc1c8e3",
+   "reftest"
+  ],
   "css/filter-effects/effect-reference-rename-001.html": [
    "6c8374536f4cf748784b7a58fc158d230ea3557f",
    "reftest"
   ],
+  "css/filter-effects/effect-reference-rename-002.html": [
+   "86528819bc7a0459a3d9c506284fc7d614049a00",
+   "reftest"
+  ],
   "css/filter-effects/empty-element-with-filter.html": [
    "3e8fc7e164cde54a8ff81a241909c2f729f32afb",
    "reftest"
@@ -441680,6 +441929,14 @@
    "918715265fa4c1b95ec46d04014ea82e73cbcd40",
    "support"
   ],
+  "css/filter-effects/reference/effect-reference-feimage-001-ref.html": [
+   "9b982b3cfb408badeb9b8b977000fc5e8935e5a6",
+   "support"
+  ],
+  "css/filter-effects/reference/effect-reference-feimage-002-ref.html": [
+   "72250a1cf802f836c2b187281fcdd38f076386b3",
+   "support"
+  ],
   "css/filter-effects/reference/effect-reference-lighting-no-light.tentative-ref.html": [
    "e863a6703b2acebbdb10a5eef342cbbd1b6b5bc9",
    "support"
@@ -441688,10 +441945,22 @@
    "5743e0c3de96ba4fbdf814bf5ec997e0c93e65da",
    "support"
   ],
+  "css/filter-effects/reference/effect-reference-obb-dimensions-ref.html": [
+   "f460c439aa8d6e56a8ad5a0826d6e0c0daf5df11",
+   "support"
+  ],
+  "css/filter-effects/reference/effect-reference-on-span-ref.html": [
+   "76a7953831720fbe9556afdc4800879c5cdd2634",
+   "support"
+  ],
   "css/filter-effects/reference/effect-reference-rename-001-ref.html": [
    "fe3beae2d4997a7603153c5c885f01c7ca656bcd",
    "support"
   ],
+  "css/filter-effects/reference/effect-reference-rename-002-ref.html": [
+   "d8719aa43a43ebbfebe6caa43b961eeee10b99c5",
+   "support"
+  ],
   "css/filter-effects/reference/empty-element-with-filter-ref.html": [
    "cf2c997f6c0d60cac9896c0b0014189cea7790bc",
    "support"
@@ -441732,6 +442001,10 @@
    "91326ef585e6910cd499ad2d6650f18fca486921",
    "support"
   ],
+  "css/filter-effects/reference/root-element-with-opacity-filter-001-ref.html": [
+   "cd16e54c8e5b73b02585c606d0133bb36c821b31",
+   "support"
+  ],
   "css/filter-effects/reference/svg-feflood-ref.html": [
    "5623b08ecd71b292e698ee249a79b59d0046300f",
    "support"
@@ -441748,6 +442021,10 @@
    "82f301f5f6ff95f743f2488093fe63ac766a84bf",
    "support"
   ],
+  "css/filter-effects/root-element-with-opacity-filter-001.html": [
+   "577e2bd4c032799a159c1c7542812e66081bfcea",
+   "reftest"
+  ],
   "css/filter-effects/support/1x1-green.png": [
    "b98ca0ba0a03c580ac339e4a3653539cfa8edc71",
    "support"
@@ -451016,6 +451293,14 @@
    "ef1b495791cad1079063180619861bfbb0d5e682",
    "testharness"
   ],
+  "dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html": [
+   "79b5f5f0186871b7c139c551faf5cf1ef15f77b9",
+   "testharness"
+  ],
+  "dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html": [
+   "63e1c3e22eaafcb84b98f542778787b7ae397ca4",
+   "testharness"
+  ],
   "dom/events/scrolling/scrollend-event-fired-to-document.html": [
    "a35508e2c557a9280802ab3d0d937fce03628e44",
    "testharness"
@@ -458757,7 +459042,7 @@
    "testharness"
   ],
   "fetch/api/response/response-error-from-stream-expected.txt": [
-   "cc50fd28741eff121d35cd7d23b5ee9da1b8bf0c",
+   "fd1e6908bfaeab27815e9edc02eaf51624d6320a",
    "support"
   ],
   "fetch/api/response/response-error-from-stream.html": [
@@ -477224,6 +477509,18 @@
    "925acfdaf8b7c2f7773b19868d0f9ba9cd0a5268",
    "testharness"
   ],
+  "html/semantics/forms/the-label-element/clicking-interactive-content.html": [
+   "60a80fad9d2aebf284e252949fba7b2bb15af134",
+   "testharness"
+  ],
+  "html/semantics/forms/the-label-element/clicking-noninteractive-labelable-content.html": [
+   "5563ef1e3c7472e8e831ee8d00c412dbcc0ef45a",
+   "testharness"
+  ],
+  "html/semantics/forms/the-label-element/clicking-noninteractive-unlabelable-content.html": [
+   "233168f5664cf972ad579ae4ccba7f674c965d25",
+   "testharness"
+  ],
   "html/semantics/forms/the-label-element/forward-focus-to-associated-element.html": [
    "86e3f652af0fb2b21d65d79da0c81a3e1daefdaa",
    "testharness"
@@ -511457,11 +511754,11 @@
    "testharness"
   ],
   "shadow-dom/slots-imperative-slot-api.tentative-expected.txt": [
-   "95f65b431e856a84ec1202c56dce6ead67e70dd5",
+   "39495dd6a5bcc6c0de06efdb57a4518be83c6d31",
    "support"
   ],
   "shadow-dom/slots-imperative-slot-api.tentative.html": [
-   "56dd71b1156cc3ac146a794e28e3b4b2bd58d143",
+   "6d3997b085c99b5163f1f1a747b792a5dbca9dea",
    "testharness"
   ],
   "shadow-dom/slots-outside-shadow-dom.html": [
@@ -521245,7 +521542,7 @@
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/safari.py": [
-   "dba8432b5a75faf402cf74042b7a59c4b66f814a",
+   "cb2b175d4dfbc3166e4ad5a6afe174ffdbc6ff8a",
    "support"
   ],
   "tools/wptrunner/wptrunner/browsers/sauce.py": [
@@ -521700,6 +521997,18 @@
    "e2d0950d5e27aa9905a9c2e1ca26242ed57fee53",
    "testharness"
   ],
+  "trust-tokens/end-to-end/README.txt": [
+   "a86468df9d6b21dfc361d178eb3afc4b3c865fea",
+   "support"
+  ],
+  "trust-tokens/end-to-end/has-trust-token-with-no-top-frame.tentative.https.html": [
+   "4788cd9907331f07abc2374b4e4b48091877fc1c",
+   "testharness"
+  ],
+  "trust-tokens/end-to-end/has-trust-token.tentative.https.html": [
+   "17e037f739391c5adcab67fc54dd8d4f0cb7764f",
+   "testharness"
+  ],
   "trust-tokens/trust-token-parameter-validation-xhr.tentative.https.html": [
    "4a6c30c6d32424c9b1d3dce883d3f44862c6e3b6",
    "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-022.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-022.html
new file mode 100644
index 0000000..943ac52
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-022.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>Minimum height of a replaced element with borders</title>
+<link rel="author" title="Google LLC" href="https://www.google.com/" />
+<link rel="help" href="http://www.w3.org/TR/css-flexbox-1/#min-size-auto" title="4.5. Implied Minimum Size of Flex Items" />
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht" />
+
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+
+<div style="height: 100px; overflow: hidden;">
+  <div style="display: flex; flex-direction: column; height: 0; width: 100px;">
+    <img src="support/1x1-green.png" style="border-bottom: 99px solid green;">
+    <div style="background-color: red; min-height: 100px;"></div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox-with-multi-column-property.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox-with-multi-column-property.html
index 5b11b0f..56b56ca 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox-with-multi-column-property.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flexbox-with-multi-column-property.html
@@ -10,6 +10,7 @@
     column-count: 2;
     column-gap: 100px;
     width: 20em;
+    font-kerning: none;
 }
 </style>
 <div class="flexbox">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/orthogonal-writing-modes-and-intrinsic-sizing.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/orthogonal-writing-modes-and-intrinsic-sizing.html
new file mode 100644
index 0000000..032cd47
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/orthogonal-writing-modes-and-intrinsic-sizing.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>CSS Flexbox: main size on orthogonal flex item.</title>
+<link rel="stylesheet" href="support/flexbox.css" >
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-base-size">
+<link rel="issue" href="https://codereview.chromium.org/1052363002">
+<meta name="assert" content="This test ensure the correct main sizes are used when flex item is orthogonal to the flex container."/>
+<style>
+.flexbox {
+  background-color: gray;
+}
+
+.vertical {
+  writing-mode: vertical-lr;
+  width: min-content;
+  background-color: blue;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.flexbox')">
+<div id=log></div>
+
+<div class="flexbox" data-expected-height="20">
+  <div class="vertical" data-expected-width="50" data-expected-height="20">
+    <div style="width: 50px; height: 20px; background-color: blue;" data-expected-width="50" data-expected-height="20"></div>
+  </div>
+</div>
+
+<div class="flexbox column" data-expected-height="20">
+  <div class="vertical" data-expected-width="50" data-expected-height="20">
+    <div style="width: 50px; height: 20px; background-color: blue;" data-expected-width="50" data-expected-height="20"></div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/css3/flexbox/percentage-sizes.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/percentage-size.html
similarity index 82%
rename from third_party/blink/web_tests/css3/flexbox/percentage-sizes.html
rename to third_party/blink/web_tests/external/wpt/css/css-flexbox/percentage-size.html
index 08ed091..44c29867 100644
--- a/third_party/blink/web_tests/css3/flexbox/percentage-sizes.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/percentage-size.html
@@ -1,4 +1,9 @@
 <!DOCTYPE html>
+<title>CSS Flexbox: Percentage size in flexbox children</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-containers">
+<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#percentage-sizing">
+<link rel="help" href="https://bugs.webkit.org/show_bug.cgi?id=81809">
+<meta name="assert" content="This test checks that percentage height/width values are correctly resolved in flexbox children.">
 <style>
 .flexbox {
     display: flex;
@@ -34,9 +39,9 @@
     background-color: purple;
 }
 </style>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/check-layout-th.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
 <body onload="checkLayout('.flexbox')">
 <div id=log></div>
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/position-relative-percentage-top-001.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/position-relative-percentage-top-001.html
new file mode 100644
index 0000000..3ec47c1d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/position-relative-percentage-top-001.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<title>CSS Flexbox: Relative position with a percentage top</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#valdef-align-items-stretch">
+<meta name="assert" content="This test ensures that a flexbox with 'flex-flow: row wrap' properly centers a grandchild with 'position: relative' and 'top: 50%'.">
+<style>
+html, body {
+  margin: 0;
+}
+
+.border {
+  border:1px solid #000;
+}
+.width-50 {
+  width: 50%;
+}
+.flex {
+  display: flex;
+  flex-flow: row wrap;
+}
+.tall {
+  height: 300px;
+}
+.top-50 {
+  position: relative;
+  top: 50%;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<body onload="checkLayout('.border')">
+<div class="border">
+  <div class="flex">
+    <div class="width-50">
+      <label class="top-50" data-offset-y="151">This should be in the center of the container</label>
+    </div>
+    <div class="width-50">
+      <div class="tall">
+        This is tall
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/active-selection-063.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/active-selection-063.html
new file mode 100644
index 0000000..1d9a1c1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/active-selection-063.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Pseudo-Elements Test: active selection and consecutive preserved &amp;Tab;</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-pseudo-4/#highlight-selectors">
+  <link rel="help" href="https://www.w3.org/TR/css-text-3/#tab-size-property">
+  <link rel="match" href="reference/ref-filled-green-100px-square.xht">
+  <link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
+
+  <meta content="" name="flags">
+  <meta name="assert" content="In this test, tab characters are preserved and converted into 4 consecutive blank spaces. The background of such blank spaces can be painted. The lines are broken after each tab character since 'white-space: pre' preserves line breaks.">
+
+  <style>
+  div
+    {
+      background-color: red;
+      color: red;
+      float: left; /* or display: inline-block or position: absolute or width: 4em */
+      font-family: Ahem;
+      font-size: 25px;
+      line-height: 1;
+      /* -moz-tab-size: 4; */
+      /*
+      Implement 'tab-size' (dropping the -moz- prefix)
+      https://bugzilla.mozilla.org/show_bug.cgi?id=737785
+      */
+      tab-size: 4;
+      white-space: pre;
+    }
+
+  div::selection
+    {
+      background-color: green;
+    }
+  </style>
+
+  <script>
+  function startTest()
+  {
+  var targetRange = document.createRange();
+  /* We first create an empty range */
+  targetRange.selectNodeContents(document.getElementById("test"));
+  /* Then we set the range boundaries to the children of div#test */
+  window.getSelection().addRange(targetRange);
+  /* Finally, we now select such range of content */
+  }
+  </script>
+
+  <body onload="startTest();">
+
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.
+
+  <div id="test">&Tab;
+&Tab;
+&Tab;
+&Tab;</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/reference/ref-filled-green-100px-square.xht b/third_party/blink/web_tests/external/wpt/css/css-pseudo/reference/ref-filled-green-100px-square.xht
new file mode 100644
index 0000000..05a1379
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/reference/ref-filled-green-100px-square.xht
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+  <title>CSS Reftest Reference</title>
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
+  <style type="text/css"><![CDATA[
+  div
+  {
+  background-color: green;
+  height: 100px;
+  width: 100px;
+  }
+  ]]></style>
+ </head>
+ <body>
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+  <div></div>
+ </body>
+</html>
diff --git a/third_party/blink/web_tests/css3/filters/filter-region-transformed-child.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-region-transformed-child-001.html
similarity index 60%
rename from third_party/blink/web_tests/css3/filters/filter-region-transformed-child.html
rename to third_party/blink/web_tests/external/wpt/css/filter-effects/filter-region-transformed-child-001.html
index ca1e9143..cd097faf7 100644
--- a/third_party/blink/web_tests/css3/filters/filter-region-transformed-child.html
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/filter-region-transformed-child-001.html
@@ -1,3 +1,8 @@
+<title>CSS Filter: Scale a transformed child element"></title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#feComponentTransferElement">
+<link rel="issue" href="https://bugs.chromium.org/p/chromium/issues/detail?id=333014">
+<link rel="match" href="reference/filter-region-transformed-child-001-ref.html">
+<meta name="assert" content="This test ensures that the feComponentTransfer filter scales a child with CSS scale transform.">
 <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="0" height="0">
   <defs>
     <filter id="filter" x="25%" y="0%" width="50%" height="100%">
diff --git a/third_party/blink/web_tests/css3/filters/filter-region-transformed-child-expected.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/filter-region-transformed-child-001-ref.html
similarity index 100%
rename from third_party/blink/web_tests/css3/filters/filter-region-transformed-child-expected.html
rename to third_party/blink/web_tests/external/wpt/css/filter-effects/reference/filter-region-transformed-child-001-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html
new file mode 100644
index 0000000..79b5f5f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-fired-for-programmatic-scroll.html
@@ -0,0 +1,134 @@
+<!DOCTYPE HTML>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="scroll_support.js"></script>
+<style>
+html {
+  height: 3000px;
+  width: 3000px;
+}
+#targetDiv {
+  width: 200px;
+  height: 200px;
+  overflow: scroll;
+}
+
+#innerDiv {
+  width: 400px;
+  height: 400px;
+}
+</style>
+
+<body style="margin:0" onload=runTest()>
+<div id="targetDiv">
+  <div id="innerDiv">
+  </div>
+</div>
+</body>
+<script>
+var element_scrollend_arrived = false;
+var document_scrollend_arrived = false;
+
+function onElementScrollEnd(event) {
+  assert_false(event.cancelable);
+  assert_false(event.bubbles);
+  element_scrollend_arrived = true;
+}
+
+function onDocumentScrollEnd(event) {
+  assert_false(event.cancelable);
+  // scrollend events are bubbled when the target node is document.
+  assert_true(event.bubbles);
+  document_scrollend_arrived = true;
+}
+
+function callScrollFunction([scrollTarget, scrollFunction, args]) {
+  scrollTarget[scrollFunction](args);
+}
+
+function runTest() {
+  let root_element = document.scrollingElement;
+  let target_div = document.getElementById("targetDiv");
+
+  promise_test (async (t) => {
+    await waitForCompositorCommit();
+    target_div.addEventListener("scrollend", onElementScrollEnd);
+    document.addEventListener("scrollend", onDocumentScrollEnd);
+
+    let test_cases = [
+      [target_div, 200, 200, [target_div, "scrollTo", { top: 200, left: 200, behavior: "auto" }]],
+      [target_div, 0, 0, [target_div, "scrollTo", { top: 0, left: 0, behavior: "smooth" }]],
+      [root_element, 200, 200, [root_element, "scrollTo", { top: 200, left: 200, behavior: "auto" }]],
+      [root_element, 0, 0, [root_element, "scrollTo", { top: 0, left: 0, behavior: "smooth" }]],
+      [target_div, 200, 200, [target_div, "scrollBy", { top: 200, left: 200, behavior: "auto" }]],
+      [target_div, 0, 0, [target_div, "scrollBy", { top: -200, left: -200, behavior: "smooth" }]],
+      [root_element, 200, 200, [root_element, "scrollBy", { top: 200, left: 200, behavior: "auto" }]],
+      [root_element, 0, 0, [root_element, "scrollBy", { top: -200, left: -200, behavior: "smooth" }]]
+    ];
+
+    for(i = 0; i < test_cases.length; i++) {
+      let t = test_cases[i];
+      let target = t[0];
+      let expected_x = t[1];
+      let expected_y = t[2];
+      let scroll_datas = t[3];
+
+      callScrollFunction(scroll_datas);
+      await waitFor(() => { return element_scrollend_arrived || document_scrollend_arrived; }, target.tagName + "." + scroll_datas[1] + " did not receive scrollend event.");
+      if (target == root_element)
+        assert_false(element_scrollend_arrived);
+      else
+        assert_false(document_scrollend_arrived);
+      assert_equals(target.scrollLeft, expected_x, target.tagName + "." + scroll_datas[1] + " scrollLeft");
+      assert_equals(target.scrollTop, expected_y, target.tagName + "." + scroll_datas[1] + " scrollTop");
+
+      element_scrollend_arrived = false;
+      document_scrollend_arrived = false;
+    }
+  }, "Tests scrollend event for calling scroll functions.");
+
+  promise_test(async (t) => {
+    await waitForCompositorCommit();
+
+    let test_cases = [
+      [target_div, "scrollTop"],
+      [target_div, "scrollLeft"],
+      [root_element, "scrollTop"],
+      [root_element, "scrollLeft"]
+    ];
+    for (i = 0; i < test_cases.length; i++) {
+      let t = test_cases[i];
+      let target = t[0];
+      let attribute = t[1];
+      let position = 200;
+
+      target.style.scrollBehavior = "smooth";
+      target[attribute] = position;
+      await waitFor(() => { return element_scrollend_arrived || document_scrollend_arrived; }, target.tagName + "." + attribute + " did not receive scrollend event.");
+      if (target == root_element)
+        assert_false(element_scrollend_arrived);
+      else
+        assert_false(document_scrollend_arrived);
+      assert_equals(target[attribute], position, target.tagName + "." + attribute + " ");
+      element_scrollend_arrived = false;
+      document_scrollend_arrived = false;
+
+      await waitForCompositorCommit();
+      target.style.scrollBehavior = "auto";
+      target[attribute] = 0;
+      await waitFor(() => { return element_scrollend_arrived || document_scrollend_arrived; }, target.tagName + "." + attribute + " did not receive scrollend event.");
+      if (target == root_element)
+        assert_false(element_scrollend_arrived);
+      else
+        assert_false(document_scrollend_arrived);
+      assert_equals(target[attribute], 0, target.tagName + "." + attribute + " ");
+      element_scrollend_arrived = false;
+      document_scrollend_arrived = false;
+    }
+  }, "Tests scrollend event for changing scroll attributes.");
+}
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html
new file mode 100644
index 0000000..63e1c3e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/scrollend-event-fired-for-scrollIntoView.html
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="scroll_support.js"></script>
+<style>
+html {
+  height: 3000px;
+  width: 3000px;
+}
+#targetDiv {
+  width: 200px;
+  height: 200px;
+  overflow: scroll;
+}
+
+#innerDiv {
+  width: 400px;
+  height: 400px;
+}
+</style>
+
+<body style="margin:0" onload=runTest()>
+<div id="targetDiv">
+  <div id="innerDiv">
+  </div>
+</div>
+</body>
+<script>
+var element_scrollend_arrived = false;
+var document_scrollend_arrived = false;
+
+function onElementScrollEnd(event) {
+  assert_false(event.cancelable);
+  assert_false(event.bubbles);
+  element_scrollend_arrived = true;
+}
+
+function onDocumentScrollEnd(event) {
+  assert_false(event.cancelable);
+  // scrollend events are bubbled when the target node is document.
+  assert_true(event.bubbles);
+  document_scrollend_arrived = true;
+}
+
+function callScrollFunction([scrollTarget, scrollFunction, args]) {
+  scrollTarget[scrollFunction](args);
+}
+
+function runTest() {
+  let root_element = document.scrollingElement;
+  let target_div = document.getElementById("targetDiv");
+  let inner_div = document.getElementById("innerDiv");
+
+  // Get expected position for root_element scrollIntoView.
+  root_element.scrollTo(10000, 10000);
+  let max_root_x = root_element.scrollLeft;
+  let max_root_y = root_element.scrollTop;
+  root_element.scrollTo(0, 0);
+
+  target_div.scrollTo(10000, 10000);
+  let max_element_x = target_div.scrollLeft;
+  let max_element_y = target_div.scrollTop;
+  target_div.scrollTo(0, 0);
+
+  promise_test (async (t) => {
+    await waitForCompositorCommit();
+    target_div.addEventListener("scrollend", onElementScrollEnd);
+    document.addEventListener("scrollend", onDocumentScrollEnd);
+
+    let test_cases = [
+      [target_div, max_element_x, max_element_y, [inner_div, "scrollIntoView", { inline: "end", block: "end", behavior: "auto" }]],
+      [target_div, 0, 0, [inner_div, "scrollIntoView", { inline: "start", block: "start", behavior: "smooth" }]],
+      [root_element, max_root_x, max_root_y, [root_element, "scrollIntoView", { inline: "end", block: "end", behavior: "smooth" }]],
+      [root_element, 0, 0, [root_element, "scrollIntoView", { inline: "start", block: "start", behavior: "smooth" }]]
+    ];
+
+    for(i = 0; i < test_cases.length; i++) {
+      let t = test_cases[i];
+      let target = t[0];
+      let expected_x = t[1];
+      let expected_y = t[2];
+      let scroll_datas = t[3];
+
+      callScrollFunction(scroll_datas);
+      await waitFor(() => { return element_scrollend_arrived || document_scrollend_arrived; }, target.tagName + ".scrollIntoView  did not receive scrollend event.");
+      if (target == root_element)
+        assert_false(element_scrollend_arrived);
+      else
+        assert_false(document_scrollend_arrived);
+      assert_equals(target.scrollLeft, expected_x, target.tagName + ".scrollIntoView scrollLeft");
+      assert_equals(target.scrollTop, expected_y, target.tagName + ".scrollIntoView scrollTop");
+
+      element_scrollend_arrived = false;
+      document_scrollend_arrived = false;
+    }
+  }, "Tests scrollend event for scrollIntoView.");
+
+  promise_test(async (t) => {
+    document.body.removeChild(target_div);
+    let out_div = document.createElement("div");
+    out_div.style = "width: 100px; height:100px; overflow:scroll; scroll-behavior:smooth;";
+    out_div.appendChild(target_div);
+    document.body.appendChild(out_div);
+    await waitForCompositorCommit();
+
+    element_scrollend_arrived = false;
+    document_scrollend_arrived = false;
+    inner_div.scrollIntoView({ inline: "end", block: "end", behavior: "auto" });
+    await waitFor(() => { return element_scrollend_arrived || document_scrollend_arrived; }, "Nested scrollIntoView did not receive scrollend event.");
+    assert_equals(root_element.scrollLeft, 0, "Nested scrollIntoView root_element scrollLeft");
+    assert_equals(root_element.scrollTop, 0, "Nested scrollIntoView root_element scrollTop");
+    assert_equals(out_div.scrollLeft, 100, "Nested scrollIntoView out_div scrollLeft");
+    assert_equals(out_div.scrollTop, 100, "Nested scrollIntoView out_div scrollTop");
+    assert_equals(target_div.scrollLeft, max_element_x, "Nested scrollIntoView target_div scrollLeft");
+    assert_equals(target_div.scrollTop, max_element_y, "Nested scrollIntoView target_div scrollTop");
+    assert_false(document_scrollend_arrived);
+  }, "Tests scrollend event for nested scrollIntoView.");
+}
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/safari.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/safari.py
index dba8432..cb2b175 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/safari.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/safari.py
@@ -3,7 +3,8 @@
 from ..webdriver_server import SafariDriverServer
 from ..executors import executor_kwargs as base_executor_kwargs
 from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
-                                           WebDriverRefTestExecutor)  # noqa: F401
+                                           WebDriverRefTestExecutor,  # noqa: F401
+                                           WebDriverCrashtestExecutor)  # noqa: F401
 from ..executors.executorsafari import SafariDriverWdspecExecutor  # noqa: F401
 
 
@@ -12,7 +13,8 @@
                  "browser": "SafariBrowser",
                  "executor": {"testharness": "WebDriverTestharnessExecutor",
                               "reftest": "WebDriverRefTestExecutor",
-                              "wdspec": "SafariDriverWdspecExecutor"},
+                              "wdspec": "SafariDriverWdspecExecutor",
+                              "crashtest": "WebDriverCrashtestExecutor"},
                  "browser_kwargs": "browser_kwargs",
                  "executor_kwargs": "executor_kwargs",
                  "env_extras": "env_extras",
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/nested-pseudo-elements-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/nested-pseudo-elements-expected.txt
index 1ca339e..23f2730 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/nested-pseudo-elements-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/nested-pseudo-elements-expected.txt
@@ -33,6 +33,10 @@
     content: "AFTER";
 
 
+Running: dumpBeforeMarkerStyles
+
+Running: dumpAfterMarkerStyles
+
 Running: removeAfterMarker
 - <div id="container">
     - <div id="inspected">
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/nested-pseudo-elements.js b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/nested-pseudo-elements.js
index 5ab2709..5e5b6cbd 100644
--- a/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/nested-pseudo-elements.js
+++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-2/nested-pseudo-elements.js
@@ -66,11 +66,19 @@
     },
 
     function dumpBeforeStyles(next) {
-      selectNodeAndDumpStyles('inspected', 'before', next);
+      selectNodeAndDumpStyles('inspected', ['before'], next);
     },
 
     function dumpAfterStyles(next) {
-      selectNodeAndDumpStyles('inspected', 'after', next);
+      selectNodeAndDumpStyles('inspected', ['after'], next);
+    },
+
+    function dumpBeforeMarkerStyles(next) {
+      selectNodeAndDumpStyles('inspected', ['before', 'marker'], next);
+    },
+
+    function dumpAfterMarkerStyles(next) {
+      selectNodeAndDumpStyles('inspected', ['after', 'marker'], next);
     },
 
     function removeAfterMarker(next) {
@@ -137,11 +145,40 @@
     }
   }
 
-  function selectNodeAndDumpStyles(id, pseudoTypeName, callback) {
-    if (pseudoTypeName)
-      ElementsTestRunner.selectPseudoElementAndWaitForStyles('inspected', pseudoTypeName, stylesCallback);
-    else
-      ElementsTestRunner.selectNodeAndWaitForStyles('inspected', stylesCallback);
+  function selectPseudoElementAndWaitForStyles(parentId, pseudoTypes, callback) {
+    if (!pseudoTypes.length) {
+      ElementsTestRunner.selectNodeAndWaitForStyles(parentId, callback);
+      return;
+    }
+
+    pseudoTypes.reduce(async function(prev, pseudoType) {
+      let prevNode = await prev;
+      function isCurrentPseudoElement(node) {
+        if (node.pseudoType() !== pseudoType)
+          return false;
+        const {parentNode} = node;
+        if (!parentNode)
+          return false;
+        if (prevNode)
+          return parentNode === prevNode;
+        return parentNode.getAttribute('id') == parentId;
+      }
+      let stylesUpdated = new Promise((resolve) => {
+        waitForStylesRebuild(isCurrentPseudoElement, resolve, true);
+      });
+      let node = await new Promise((resolve) => {
+        ElementsTestRunner.findNode(isCurrentPseudoElement, resolve);
+      });
+      if (!node)
+        throw new Error("Can't find node");
+      Common.Revealer.reveal(node);
+      await stylesUpdated;
+      return node;
+    }, null).then(callback);
+  }
+
+  function selectNodeAndDumpStyles(id, pseudoTypeNames, callback) {
+    selectPseudoElementAndWaitForStyles(id, pseudoTypeNames, stylesCallback);
 
     async function stylesCallback() {
       await ElementsTestRunner.dumpSelectedElementStyles(true, false, false, true);
diff --git a/third_party/blink/web_tests/http/tests/local/drag-over-remote-content-expected.txt b/third_party/blink/web_tests/http/tests/local/drag-over-remote-content-expected.txt
deleted file mode 100644
index 49cfff1b0..0000000
--- a/third_party/blink/web_tests/http/tests/local/drag-over-remote-content-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This page just embeds drag-over-remote-content-iframe.html in an iframe. See its results below:
-
-PASS: ondragover saw a URL of ''
-
diff --git a/third_party/blink/web_tests/http/tests/local/drag-over-remote-content.html b/third_party/blink/web_tests/http/tests/local/drag-over-remote-content.html
deleted file mode 100644
index ca167d6..0000000
--- a/third_party/blink/web_tests/http/tests/local/drag-over-remote-content.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<p>This page just embeds drag-over-remote-content-iframe.html in an iframe. See its results below:</p>
-<pre id="console"></pre>
-<script>
-window.addEventListener('message', (e) => {
-    document.getElementById("console").appendChild(document.createTextNode(e.data + "\n"));
-    if (window.testRunner)
-        testRunner.notifyDone();
-});
-</script>
-<iframe width="100%" height="100%" src="http://127.0.0.1:8000/security/drag-over-remote-content-iframe.html"></iframe>
-<script>
-if (window.testRunner)
-    testRunner.waitUntilDone();
-</script>
diff --git a/third_party/blink/web_tests/inspector-protocol/css/nested-pseudo-element-matching-selectors-expected.txt b/third_party/blink/web_tests/inspector-protocol/css/nested-pseudo-element-matching-selectors-expected.txt
new file mode 100644
index 0000000..f8369caa
--- /dev/null
+++ b/third_party/blink/web_tests/inspector-protocol/css/nested-pseudo-element-matching-selectors-expected.txt
@@ -0,0 +1,8 @@
+Test that matching styles report nested pseudo element styles.
+
+=== Dump matching styles for #for-pseudo::before::marker ===
+
+
+=== Dump matching styles for #for-pseudo::after::marker ===
+
+
diff --git a/third_party/blink/web_tests/inspector-protocol/css/nested-pseudo-element-matching-selectors.js b/third_party/blink/web_tests/inspector-protocol/css/nested-pseudo-element-matching-selectors.js
new file mode 100644
index 0000000..081815e
--- /dev/null
+++ b/third_party/blink/web_tests/inspector-protocol/css/nested-pseudo-element-matching-selectors.js
@@ -0,0 +1,57 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startHTML(`
+<style>
+::marker {
+  content: "This should NOT match";
+}
+#for-pseudo::before {
+  content: "BEFORE";
+  display: list-item;
+}
+#for-pseudo::after {
+  content: "AFTER";
+  display: list-item;
+}
+#for-pseudo::before::marker {
+  content: "MARKER";
+}
+</style>
+<div id='for-pseudo'>Test</div>`, 'Test that matching styles report nested pseudo element styles.');
+  await dp.DOM.enable();
+  await dp.CSS.enable();
+
+  const NodeTracker = await testRunner.loadScript('../resources/node-tracker.js');
+  const nodeTracker = new NodeTracker(dp);
+  const DOMHelper = await testRunner.loadScript('../resources/dom-helper.js');
+  const CSSHelper = await testRunner.loadScript('../resources/css-helper.js');
+  const cssHelper = new CSSHelper(testRunner, dp);
+
+  function getPseudoElement(node, ...pseudoTypes) {
+    for (const pseudoType of pseudoTypes)
+      node = node.pseudoElements.find(pseudoElement => pseudoElement.pseudoType === pseudoType);
+    return node;
+  }
+
+  async function loadAndDumpMatchingRules(nodeId) {
+    const {result} = await dp.CSS.getMatchedStylesForNode({nodeId});
+    for (const ruleMatch of result.matchedCSSRules) {
+      const origin = ruleMatch.rule.origin;
+      if (origin !== 'inspector' && origin !== 'regular')
+        continue;
+      cssHelper.dumpRuleMatch(ruleMatch);
+    }
+  }
+
+  const documentNodeId = await cssHelper.requestDocumentNodeId();
+  await cssHelper.requestNodeId(documentNodeId, '#for-pseudo');
+
+  const node = nodeTracker.nodes().find(node => DOMHelper.attributes(node).get('id') === 'for-pseudo');
+
+  testRunner.log('\n=== Dump matching styles for #for-pseudo::before::marker ===\n');
+  await loadAndDumpMatchingRules(getPseudoElement(node, "before", "marker").nodeId);
+
+  testRunner.log('\n=== Dump matching styles for #for-pseudo::after::marker ===\n');
+  await loadAndDumpMatchingRules(getPseudoElement(node, "after", "marker").nodeId);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/virtual/not-site-per-process/http/tests/local/drag-over-remote-content-expected.txt b/third_party/blink/web_tests/virtual/not-site-per-process/http/tests/local/drag-over-remote-content-expected.txt
deleted file mode 100644
index 49cfff1b0..0000000
--- a/third_party/blink/web_tests/virtual/not-site-per-process/http/tests/local/drag-over-remote-content-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This page just embeds drag-over-remote-content-iframe.html in an iframe. See its results below:
-
-PASS: ondragover saw a URL of ''
-
diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn
index 1f57237..7a64381 100644
--- a/third_party/zlib/BUILD.gn
+++ b/third_party/zlib/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/compiler/compiler.gni")
+import("//testing/test.gni")
 
 if (current_cpu == "arm" || current_cpu == "arm64") {
   import("//build/config/arm.gni")
@@ -384,3 +385,17 @@
 
   deps = [ ":zlib" ]
 }
+
+test("zlib_unittests") {
+  sources = [
+    "contrib/tests/utils_unittest.cc",
+    "google/compression_utils_portable.cc",
+    "google/compression_utils_portable.h",
+  ]
+
+  deps = [
+    ":zlib",
+    "//testing/gtest",
+    "//testing/gtest:gtest_main",
+  ]
+}
diff --git a/third_party/zlib/DEPS b/third_party/zlib/DEPS
new file mode 100644
index 0000000..b6dcfc6
--- /dev/null
+++ b/third_party/zlib/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+    "+testing/gtest",
+]
\ No newline at end of file
diff --git a/third_party/zlib/contrib/tests/utils_unittest.cc b/third_party/zlib/contrib/tests/utils_unittest.cc
new file mode 100644
index 0000000..6e1f5c98
--- /dev/null
+++ b/third_party/zlib/contrib/tests/utils_unittest.cc
@@ -0,0 +1,58 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the Chromium source repository LICENSE file.
+
+#include <cstddef>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/zlib/google/compression_utils_portable.h"
+
+#include "zlib.h"
+
+void TestPayloads(size_t input_size, zlib_internal::WrapperType type) {
+  std::vector<unsigned char> input;
+  input.reserve(input_size);
+  for (size_t i = 1; i <= input_size; ++i)
+    input.push_back(i & 0xff);
+
+  // If it is big enough for GZIP, will work for other wrappers.
+  std::vector<unsigned char> compressed(
+      zlib_internal::GzipExpectedCompressedSize(input.size()));
+  std::vector<unsigned char> decompressed(input.size());
+
+  // Libcores's java/util/zip/Deflater default settings: ZLIB,
+  // DEFAULT_COMPRESSION and DEFAULT_STRATEGY.
+  unsigned long compressed_size = static_cast<unsigned long>(compressed.size());
+  int result = zlib_internal::CompressHelper(
+      type, compressed.data(), &compressed_size, input.data(), input.size(),
+      Z_DEFAULT_COMPRESSION, nullptr, nullptr);
+  ASSERT_EQ(result, Z_OK);
+
+  unsigned long decompressed_size =
+      static_cast<unsigned long>(decompressed.size());
+  result = zlib_internal::UncompressHelper(type, decompressed.data(),
+                                           &decompressed_size,
+                                           compressed.data(), compressed_size);
+  ASSERT_EQ(result, Z_OK);
+  EXPECT_EQ(input, decompressed);
+}
+
+TEST(ZlibTest, ZlibWrapper) {
+  // Minimal ZLIB wrapped short stream size is about 8 bytes.
+  for (size_t i = 1; i < 1024; ++i)
+    TestPayloads(i, zlib_internal::WrapperType::ZLIB);
+}
+
+TEST(ZlibTest, GzipWrapper) {
+  // GZIP should be 12 bytes bigger than ZLIB wrapper.
+  for (size_t i = 1; i < 1024; ++i)
+    TestPayloads(i, zlib_internal::WrapperType::GZIP);
+}
+
+TEST(ZlibTest, RawWrapper) {
+  // RAW has no wrapper (V8 Blobs is a known user), size
+  // should be payload_size + 2 for short payloads.
+  for (size_t i = 1; i < 1024; ++i)
+    TestPayloads(i, zlib_internal::WrapperType::ZRAW);
+}
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 3af6995a..4ee5a15 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -37671,6 +37671,7 @@
   <int value="-1940806558" label="enable-syncfs-directory-operation"/>
   <int value="-1940377152" label="MacRTL:enabled"/>
   <int value="-1940291343" label="SpeculativeResourcePrefetching:enabled"/>
+  <int value="-1939533266" label="LauncherSettingsSearch:enabled"/>
   <int value="-1939016096"
       label="OmniboxUIExperimentHideSuggestionUrlTrivialSubdomains:enabled"/>
   <int value="-1939003674" label="NetworkServiceInProcess:disabled"/>
@@ -37984,6 +37985,7 @@
   <int value="-1571841513" label="enable-devtools-experiments"/>
   <int value="-1568559155" label="WebSocketHandshakeReuseConnection:enabled"/>
   <int value="-1567727398" label="DesktopPWAsWithoutExtensions:disabled"/>
+  <int value="-1561360053" label="LauncherSettingsSearch:disabled"/>
   <int value="-1561252720" label="AutofillCreditCardUploadFeedback:disabled"/>
   <int value="-1560729847" label="AutofillCacheQueryResponses:enabled"/>
   <int value="-1560650271" label="WasmCodeCache:disabled"/>
@@ -38152,6 +38154,7 @@
   <int value="-1391645613" label="ImeMozcProto:enabled"/>
   <int value="-1390331361"
       label="SyncPseudoUSSHistoryDeleteDirectives:enabled"/>
+  <int value="-1390005994" label="AppCache:disabled"/>
   <int value="-1388817073" label="OmniboxReverseAnswers:disabled"/>
   <int value="-1386966873" label="disable-mac-views-native-app-windows"/>
   <int value="-1386790338" label="ImeMozcProto:disabled"/>
@@ -39919,6 +39922,7 @@
   <int value="684806628" label="TranslateLanguageByULP:disabled"/>
   <int value="685916283" label="enable-zip-archiver-on-file-manager"/>
   <int value="687838135" label="ThirdPartyDoodles:disabled"/>
+  <int value="688254068" label="AppCache:enabled"/>
   <int value="689489984" label="disable-zero-suggest"/>
   <int value="689577480" label="vr-shell-experimental-rendering"/>
   <int value="690185633" label="NonValidatingReloadOnNormalReload:disabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index a3d02b8..b983019 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -12486,7 +12486,7 @@
 </histogram>
 
 <histogram name="Autofill.Address.IsEnabled.PageLoad" enum="BooleanEnabled"
-    expires_after="2020-05-01">
+    expires_after="2021-04-01">
   <owner>jsaul@google.com</owner>
   <owner>chrome-autofill@google.com</owner>
   <summary>
@@ -12496,7 +12496,7 @@
 </histogram>
 
 <histogram name="Autofill.Address.IsEnabled.Startup" enum="BooleanEnabled"
-    expires_after="2020-05-01">
+    expires_after="2021-04-01">
   <owner>jsaul@google.com</owner>
   <owner>chrome-autofill@google.com</owner>
   <summary>
@@ -12838,7 +12838,7 @@
 </histogram>
 
 <histogram name="Autofill.CardUnmask.CvcLength" units="digits"
-    expires_after="M83">
+    expires_after="M86">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>payments-autofill-team@google.com</owner>
@@ -12916,7 +12916,7 @@
 </histogram>
 
 <histogram name="Autofill.CreditCard.IsEnabled.PageLoad" enum="BooleanEnabled"
-    expires_after="2020-05-01">
+    expires_after="2021-04-01">
   <owner>jsaul@google.com</owner>
   <owner>chrome-autofill@google.com</owner>
   <summary>
@@ -12926,7 +12926,7 @@
 </histogram>
 
 <histogram name="Autofill.CreditCard.IsEnabled.Startup" enum="BooleanEnabled"
-    expires_after="2020-05-01">
+    expires_after="2021-04-01">
   <owner>jsaul@google.com</owner>
   <owner>chrome-autofill@google.com</owner>
   <summary>
@@ -13405,21 +13405,31 @@
 </histogram>
 
 <histogram name="Autofill.IsEnabled.PageLoad" enum="BooleanEnabled"
-    expires_after="2020-05-01">
+    expires_after="2021-04-01">
   <owner>jsaul@google.com</owner>
   <owner>battre@chromium.org</owner>
   <owner>chrome-autofill@google.com</owner>
   <summary>
-    Tracks whether Autofill is enabled on page load for a page containing forms.
+    This includes Autofill.Address.IsEnabled.PageLoad and
+    Autofill.CreditCard.IsEnabled.PageLoad, and tracks whether either profile
+    Autofill or payment Autofill is enabled on page load for a page containing
+    forms. It helps deduce the overlap by showing what percentage of users have
+    one type of Autofill enabled but not the other.
   </summary>
 </histogram>
 
 <histogram name="Autofill.IsEnabled.Startup" enum="BooleanEnabled"
-    expires_after="2020-05-01">
+    expires_after="2021-04-01">
   <owner>jsaul@google.com</owner>
   <owner>battre@chromium.org</owner>
   <owner>chrome-autofill@google.com</owner>
-  <summary>Tracks whether Autofill is enabled when Chrome launches.</summary>
+  <summary>
+    This includes Autofill.Address.IsEnabled.Startup and
+    Autofill.CreditCard.IsEnabled.Startup, and tracks whether either profile
+    Autofill or payment Autofill is enabled when Chrome launches. It helps
+    deduce the overlap by showing what percentage of users have one type of
+    Autofill enabled but not the other.
+  </summary>
 </histogram>
 
 <histogram name="Autofill.KeyboardAccessoryButtonsIOS_ScreenReaderOff"
@@ -100672,6 +100682,9 @@
 
 <histogram name="NewTabPage.ContentSuggestions.ArticleFaviconFetchResult"
     enum="FaviconFetchResult" expires_after="M77">
+  <obsolete>
+    Not used anymore. Removed in April 2020.
+  </obsolete>
   <owner>jkrcal@chromium.org</owner>
   <summary>
     Android: Result of fetching a favicon for an article suggestion on the New
@@ -100681,6 +100694,9 @@
 
 <histogram name="NewTabPage.ContentSuggestions.ArticleFaviconFetchTime"
     units="ms" expires_after="M77">
+  <obsolete>
+    Not used anymore. Removed in April 2020.
+  </obsolete>
   <owner>jkrcal@chromium.org</owner>
   <summary>
     Android: Time it takes to fetch a favicon for an article suggestion on the
@@ -101340,6 +101356,9 @@
 
 <histogram name="NewTabPage.ContentSuggestions.UIUpdateResult2"
     enum="ContentSuggestionsUIUpdateResult2" expires_after="M77">
+  <obsolete>
+    Not used anymore. Removed in April 2020.
+  </obsolete>
   <owner>jkrcal@chromium.org</owner>
   <summary>
     Android: The result of updating the list of content suggestions in one UI
@@ -101350,6 +101369,9 @@
 <histogram
     name="NewTabPage.ContentSuggestions.UIUpdateSuccessNumberOfSuggestionsSeen"
     units="suggestions" expires_after="M78">
+  <obsolete>
+    Not used anymore. Removed in April 2020.
+  </obsolete>
   <owner>jkrcal@chromium.org</owner>
   <summary>
     Android: The number of content suggestions that have been seen by the user
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 0940c4a..3f4b868 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -5375,6 +5375,21 @@
     Event recorded when RequestMediaKeySystemAccess() is called as part of
     Encrypted Media Extensions (EME) API.
   </summary>
+  <metric name="IsAdFrame">
+    <summary>
+      Whether the frame is an ad frame.
+    </summary>
+  </metric>
+  <metric name="IsCrossOrigin">
+    <summary>
+      Whether the frame is Cross-Origin to the main frame.
+    </summary>
+  </metric>
+  <metric name="IsTopFrame">
+    <summary>
+      Whether the frame is the main frame.
+    </summary>
+  </metric>
   <metric name="KeySystem">
     <summary>
       The key system passed in requestMediaKeySystemAccess() call.
diff --git a/tools/win/trim_heap/.gitignore b/tools/win/trim_heap/.gitignore
new file mode 100644
index 0000000..78c5f36a
--- /dev/null
+++ b/tools/win/trim_heap/.gitignore
@@ -0,0 +1,3 @@
+.vs/
+trim_heap.obj
+trim_heap.exe
diff --git a/tools/win/trim_heap/OWNERS b/tools/win/trim_heap/OWNERS
new file mode 100644
index 0000000..9969d28
--- /dev/null
+++ b/tools/win/trim_heap/OWNERS
@@ -0,0 +1,3 @@
+brucedawson@chromium.org
+davidbienvenu@chromium.org
+jessemckenna@chromium.org
diff --git a/tools/win/trim_heap/build.bat b/tools/win/trim_heap/build.bat
new file mode 100755
index 0000000..1bdca77
--- /dev/null
+++ b/tools/win/trim_heap/build.bat
@@ -0,0 +1,15 @@
+@setlocal

+

+where cl

+if errorlevel 1 goto no_cl

+

+pushd %~dp0

+cl /nologo /Zi /GS- /EHsc trim_heap.cc /link /DEBUG /OPT:REF /OPT:ICF

+popd

+

+exit /b

+

+:no_cl

+@echo Run "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvarsall.bat" amd64

+@echo or equivalent to get the 64-bit compiler tools in the path.

+exit /b

diff --git a/tools/win/trim_heap/trim_heap.cc b/tools/win/trim_heap/trim_heap.cc
new file mode 100644
index 0000000..417a8e0
--- /dev/null
+++ b/tools/win/trim_heap/trim_heap.cc
@@ -0,0 +1,188 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is an experimental tool which will inject a thread into a Chrome
+// process (tested on the browser process) and run code to call
+// HeapSetInformation with HEAP_OPTIMIZE_RESOURCES_CURRENT_VERSION. This
+// tells Windows to trim unnecessary memory from the heaps in that process.
+//
+// This tool uses sketchy techniques such as copying memory from one
+// executable to another (only works if the code is relocatable and has no
+// external references), VirtualAllocEx, and CreateRemoteThread. This is not
+// for production use.
+//
+// The bitness of this tool (32/64) must match that of the target process.
+// This tool has only been tested on 64-bit processes. This tool only works
+// when compiled with optimizations.
+//
+// Some error handling and resource cleanup is omitted in order to keep things
+// simple.
+
+#include <Windows.h>
+
+// Psapi.h must come after Windows.h.
+#include <Psapi.h>
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <vector>
+
+#ifdef _DEBUG
+#error This code only works in optimized (release) builds.
+// Non-optimized code may include references to global variables. The
+// "#pragma clang optimize on/off" directives do not work, by design, in debug
+// builds. They can only lower the optimization level, not raise it.
+#endif
+
+#define ADDRESS_COOKIE reinterpret_cast<void*>(0x123456789ABCDEF0)
+
+// Function suitable for copying into another process and invoking with
+// CreateRemoteThread. The function address is a placeholder.
+DWORD WINAPI ShrinkHeapThread(LPVOID) {
+  auto pHeapSetInformation =
+      reinterpret_cast<decltype(&::HeapSetInformation)>(ADDRESS_COOKIE);
+  HEAP_OPTIMIZE_RESOURCES_INFORMATION info = {
+      HEAP_OPTIMIZE_RESOURCES_CURRENT_VERSION, 0x0};
+  pHeapSetInformation(nullptr, HeapOptimizeResources, &info, sizeof(info));
+  return 0;
+}
+
+int main(int argc, char* argv[]) {
+  const bool verbose = false;
+
+  // Verify that we have the correct signature for ShrinkHeapThread.
+  static_assert(
+      std::is_same<decltype(ShrinkHeapThread)*, PTHREAD_START_ROUTINE>::value,
+      "Callback function is wrong type.");
+
+  // Copy the thread function's memory to a vector.
+  std::vector<unsigned char> raw_bytes;
+  auto* src = reinterpret_cast<uint8_t*>(&ShrinkHeapThread);
+  // Assume that the only 0xc3 byte we will encounter will be the ret
+  // instruction.
+  uint8_t ret = 0xc3;
+  while (*src != ret) {
+    raw_bytes.push_back(*src++);
+  }
+  raw_bytes.push_back(ret);
+  if (src[1] != 0xcc) {
+    printf("Didn't find int 3 after ret. Exiting.\n");
+    return 1;
+  }
+  // This can trigger if incremental linking is enabled since then the function
+  // pointer will be to a JMP stub.
+  if (raw_bytes.size() > 1000) {
+    printf("Code size is suspiciously large - %zu bytes. Exiting.\n",
+           raw_bytes.size());
+    return 1;
+  }
+
+  // Update the function pointer address in the copy to match the current
+  // address of HeapSetInformation. This assumes that the address will be the
+  // same in all processes, which should be the case.
+  for (auto* scan = &raw_bytes[0]; /**/; ++scan) {
+    auto** scan_64 = reinterpret_cast<void**>(scan);
+    if (*scan_64 == ADDRESS_COOKIE) {
+      auto* pHeapSetInformation = reinterpret_cast<void*>(GetProcAddress(
+          GetModuleHandleA("kernel32.dll"), "HeapSetInformation"));
+      *scan_64 = pHeapSetInformation;
+      if (verbose)
+        printf("Found and updated HeapSetInformation.\n");
+      break;
+    }
+  }
+
+  if (argc < 2) {
+    printf("Usage: %s PID.\n", argv[0]);
+    printf(
+        "Injects code into the target process to call HeapSetInformation with "
+        "HEAP_OPTIMIZE_RESOURCES_CURRENT_VERSION.\n");
+    printf(
+        "May need to be run from an administrator command prompt for some "
+        "processes.\n");
+    return 1;
+  }
+
+  // Get the PIDs from the command line.
+  for (int i = 1; i < argc; ++i) {
+    int PID;
+    if (sscanf(argv[i], "%d", &PID) != 1) {
+      printf("Error getting PID.\n");
+      return 1;
+    }
+
+    // Open the process. We'll leak the handle afterwards, but that's okay
+    // because this is a short-lived tool.
+    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ |
+                                      PROCESS_VM_WRITE | PROCESS_VM_OPERATION |
+                                      PROCESS_CREATE_THREAD,
+                                  false, PID);
+    if (!hProcess) {
+      printf("Error from OpenProcess is %lx.\n", GetLastError());
+      return 1;
+    }
+
+#ifdef _M_X64
+    BOOL wow_64_process = FALSE;
+    if (!IsWow64Process(hProcess, &wow_64_process) || wow_64_process) {
+      printf("Specified process is 32-bit. Code injection will not work.\n");
+      return 1;
+    }
+#else
+    // Update this with remote-process bitness tests if x86 works.
+#error This code is only tested on x64 and may cause failures on x86.
+#endif
+
+    PROCESS_MEMORY_COUNTERS_EX memory_before = {sizeof(memory_before)};
+    GetProcessMemoryInfo(
+        hProcess, reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&memory_before),
+        sizeof(memory_before));
+
+    // Allocate memory in the other process.
+    void* p = VirtualAllocEx(hProcess, nullptr, raw_bytes.size(),
+                             MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+
+    if (verbose)
+      printf("Writing %zd bytes to process %d at address 0x%p.\n",
+             raw_bytes.size(), PID, p);
+    // Write to the remotely allocated memory.
+    SIZE_T bytes_written = 0;
+    if (!WriteProcessMemory(hProcess, p, &raw_bytes[0], raw_bytes.size(),
+                            &bytes_written)) {
+      printf("Error is %lx.\n", GetLastError());
+      return 1;
+    }
+
+    if (verbose)
+      printf("Wrote %zd bytes.\n", bytes_written);
+    HANDLE hRemoteThread = CreateRemoteThread(
+        hProcess, nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(p),
+        nullptr, 0, nullptr);
+    if (!hRemoteThread) {
+      printf("Failed to inject thread in process %d. Error code is %lx.\n", PID,
+             GetLastError());
+      return 1;
+    }
+
+    if (verbose)
+      printf("Successfully injected thread into process %d.\n", PID);
+    WaitForSingleObject(hRemoteThread, INFINITE);
+    // Clean up the allocated memory after the thread exits.
+    VirtualFreeEx(hProcess, p, 0, MEM_RELEASE);
+
+    PROCESS_MEMORY_COUNTERS_EX memory_after = {sizeof(memory_after)};
+    GetProcessMemoryInfo(
+        hProcess, reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&memory_after),
+        sizeof(memory_after));
+
+    double MiB = 1024.0 * 1024.0;
+    printf(
+        "  Commit for process %6d went from %8.3f MiB to %8.3f MiB (%7.3f MiB "
+        "savings).\n",
+        PID, memory_before.PrivateUsage / MiB, memory_after.PrivateUsage / MiB,
+        (memory_before.PrivateUsage - memory_after.PrivateUsage) / MiB);
+  }
+  return 0;
+}
diff --git a/tools/win/trim_heap/trim_loop.bat b/tools/win/trim_heap/trim_loop.bat
new file mode 100755
index 0000000..9505f5c2
--- /dev/null
+++ b/tools/win/trim_heap/trim_loop.bat
@@ -0,0 +1,9 @@
+call build

+

+@echo off

+

+:top

+echo Trimming heaps at %time%

+trim_heap %*

+sleep 300

+goto top

diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom
index 877976f..42250f2 100644
--- a/ui/accessibility/ax_enums.mojom
+++ b/ui/accessibility/ax_enums.mojom
@@ -242,7 +242,7 @@
   kMath,
   kMenu,
   kMenuBar,
-  kMenuButton,
+  kMenuButton, // TODO: kMenuButton is not used anywhere, consider removal.
   kMenuItem,
   kMenuItemCheckBox,
   kMenuItemRadio,
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc
index 3ad412f2..ecbe8c3 100644
--- a/ui/accessibility/ax_node_data.cc
+++ b/ui/accessibility/ax_node_data.cc
@@ -880,6 +880,16 @@
   }
 }
 
+bool AXNodeData::IsButtonPressed() const {
+  // Currently there is no internal representation for |aria-pressed|, and
+  // we map |aria-pressed="true"| to ax::mojom::CheckedState::kTrue for a native
+  // button or role="button".
+  // https://www.w3.org/TR/wai-aria-1.1/#aria-pressed
+  if (IsButton(role) && GetCheckedState() == ax::mojom::CheckedState::kTrue)
+    return true;
+  return false;
+}
+
 bool AXNodeData::IsClickable() const {
   // If it has a custom default action verb except for
   // ax::mojom::DefaultActionVerb::kClickAncestor, it's definitely clickable.
@@ -907,6 +917,20 @@
          !ui::SupportsToggle(role);
 }
 
+bool AXNodeData::IsMenuButton() const {
+  // According to the WAI-ARIA spec, a menu button is a native button or an ARIA
+  // role="button" that opens a menu. Although ARIA does not include a role
+  // specifically for menu buttons, screen readers identify buttons that have
+  // aria-haspopup="true" or aria-haspopup="menu" as menu buttons, and Blink
+  // maps both to HasPopup::kMenu.
+  // https://www.w3.org/TR/wai-aria-practices/#menubutton
+  // https://www.w3.org/TR/wai-aria-1.1/#aria-haspopup
+  if (IsButton(role) && GetHasPopup() == ax::mojom::HasPopup::kMenu)
+    return true;
+
+  return false;
+}
+
 bool AXNodeData::IsPlainTextField() const {
   // We need to check both the role and editable state, because some ARIA text
   // fields may in fact not be editable, whilst some editable fields might not
diff --git a/ui/accessibility/ax_node_data.h b/ui/accessibility/ax_node_data.h
index 36dbf00..8fd95146 100644
--- a/ui/accessibility/ax_node_data.h
+++ b/ui/accessibility/ax_node_data.h
@@ -190,6 +190,10 @@
   ax::mojom::ImageAnnotationStatus GetImageAnnotationStatus() const;
   void SetImageAnnotationStatus(ax::mojom::ImageAnnotationStatus status);
 
+  // Helper to determine if the data belongs to a node that is a native button
+  // or ARIA role="button" in a pressed state.
+  bool IsButtonPressed() const;
+
   // Helper to determine if the data belongs to a node that can respond to
   // clicks.
   bool IsClickable() const;
@@ -200,6 +204,9 @@
   // Helper to determine if the data belongs to a node that is invocable.
   bool IsInvocable() const;
 
+  // Helper to determine if the data belongs to a node that is a menu button.
+  bool IsMenuButton() const;
+
   // Helper to determine if the data belongs to a node that is a plain
   // textfield.
   bool IsPlainTextField() const;
diff --git a/ui/accessibility/ax_node_data_unittest.cc b/ui/accessibility/ax_node_data_unittest.cc
index 4ae414f2d..4abf80b 100644
--- a/ui/accessibility/ax_node_data_unittest.cc
+++ b/ui/accessibility/ax_node_data_unittest.cc
@@ -81,7 +81,51 @@
   EXPECT_TRUE(moved_styles == node_1.GetTextStyles());
 }
 
-TEST(AXNodeDataTest, TestIsClickable) {
+TEST(AXNodeDataTest, IsButtonPressed) {
+  // A non-button element with CheckedState::kTrue should not return true for
+  // IsButtonPressed.
+  AXNodeData non_button_pressed;
+  non_button_pressed.role = ax::mojom::Role::kGenericContainer;
+  non_button_pressed.SetCheckedState(ax::mojom::CheckedState::kTrue);
+  EXPECT_FALSE(IsButton(non_button_pressed.role));
+  EXPECT_FALSE(non_button_pressed.IsButtonPressed());
+
+  // A button element with CheckedState::kTrue should return true for
+  // IsButtonPressed.
+  AXNodeData button_pressed;
+  button_pressed.role = ax::mojom::Role::kButton;
+  button_pressed.SetCheckedState(ax::mojom::CheckedState::kTrue);
+  EXPECT_TRUE(IsButton(button_pressed.role));
+  EXPECT_TRUE(button_pressed.IsButtonPressed());
+
+  button_pressed.role = ax::mojom::Role::kPopUpButton;
+  EXPECT_TRUE(IsButton(button_pressed.role));
+  EXPECT_TRUE(button_pressed.IsButtonPressed());
+
+  button_pressed.role = ax::mojom::Role::kToggleButton;
+  EXPECT_TRUE(IsButton(button_pressed.role));
+  EXPECT_TRUE(button_pressed.IsButtonPressed());
+
+  // A button element does not have CheckedState::kTrue should return false for
+  // IsButtonPressed.
+  AXNodeData button_not_pressed;
+  button_not_pressed.role = ax::mojom::Role::kButton;
+  button_not_pressed.SetCheckedState(ax::mojom::CheckedState::kNone);
+  EXPECT_TRUE(IsButton(button_not_pressed.role));
+  EXPECT_FALSE(button_not_pressed.IsButtonPressed());
+
+  button_not_pressed.role = ax::mojom::Role::kPopUpButton;
+  button_not_pressed.SetCheckedState(ax::mojom::CheckedState::kFalse);
+  EXPECT_TRUE(IsButton(button_not_pressed.role));
+  EXPECT_FALSE(button_not_pressed.IsButtonPressed());
+
+  button_not_pressed.role = ax::mojom::Role::kToggleButton;
+  button_not_pressed.SetCheckedState(ax::mojom::CheckedState::kMixed);
+  EXPECT_TRUE(IsButton(button_not_pressed.role));
+  EXPECT_FALSE(button_not_pressed.IsButtonPressed());
+}
+
+TEST(AXNodeDataTest, IsClickable) {
   // Test for ax node data attribute with a custom default action verb.
   AXNodeData data_default_action_verb;
 
@@ -154,7 +198,7 @@
   }
 }
 
-TEST(AXNodeDataTest, TestIsInvocable) {
+TEST(AXNodeDataTest, IsInvocable) {
   // Test for iterating through all roles and validate if a role is invocable.
   // A role is invocable if it is clickable and supports neither expand collpase
   // nor toggle.
@@ -182,7 +226,41 @@
   }
 }
 
-TEST(AXNodeDataTest, TestSupportsExpandCollapse) {
+TEST(AXNodeDataTest, IsMenuButton) {
+  // A non button element should return false for IsMenuButton.
+  AXNodeData non_button;
+  non_button.role = ax::mojom::Role::kGenericContainer;
+  EXPECT_FALSE(IsButton(non_button.role));
+  EXPECT_FALSE(non_button.IsMenuButton());
+
+  // Only button element with HasPopup::kMenu should return true for
+  // IsMenuButton. All other ax::mojom::HasPopup types should return false.
+  AXNodeData button_with_popup;
+
+  button_with_popup.role = ax::mojom::Role::kButton;
+
+  for (int has_popup_idx = static_cast<int>(ax::mojom::HasPopup::kMinValue);
+       has_popup_idx <= static_cast<int>(ax::mojom::HasPopup::kMaxValue);
+       has_popup_idx++) {
+    button_with_popup.SetHasPopup(
+        static_cast<ax::mojom::HasPopup>(has_popup_idx));
+    bool is_menu_button = button_with_popup.IsMenuButton();
+
+    SCOPED_TRACE(testing::Message()
+                 << "ax::mojom::Role=" << ToString(button_with_popup.role)
+                 << ", hasPopup=" << button_with_popup.GetHasPopup()
+                 << ", Actual: isMenuButton=" << is_menu_button
+                 << ", Expected: isMenuButton=" << !is_menu_button);
+
+    if (IsButton(button_with_popup.role) &&
+        button_with_popup.GetHasPopup() == ax::mojom::HasPopup::kMenu)
+      EXPECT_TRUE(is_menu_button);
+    else
+      EXPECT_FALSE(is_menu_button);
+  }
+}
+
+TEST(AXNodeDataTest, SupportsExpandCollapse) {
   // Test for iterating through all hasPopup attributes and validate if a
   // hasPopup attribute supports expand collapse.
   AXNodeData data_has_popup;
diff --git a/ui/accessibility/ax_role_properties.cc b/ui/accessibility/ax_role_properties.cc
index c72c580..481c7a87 100644
--- a/ui/accessibility/ax_role_properties.cc
+++ b/ui/accessibility/ax_role_properties.cc
@@ -52,6 +52,19 @@
   }
 }
 
+bool IsButton(const ax::mojom::Role role) {
+  // According to the WAI-ARIA spec, native button or role="button"
+  // supports |aria-expanded| and |aria-pressed|.
+  // If the button has |aria-expanded| set, then it takes on
+  // Role::kPopUpButton.
+  // If the button has |aria-pressed| set, then it takes on
+  // Role::kToggleButton.
+  // https://www.w3.org/TR/wai-aria-1.1/#button
+  return role == ax::mojom::Role::kButton ||
+         role == ax::mojom::Role::kPopUpButton ||
+         role == ax::mojom::Role::kToggleButton;
+}
+
 bool IsClickable(const ax::mojom::Role role) {
   switch (role) {
     case ax::mojom::Role::kButton:
diff --git a/ui/accessibility/ax_role_properties.h b/ui/accessibility/ax_role_properties.h
index d601cdc8..acf76ed 100644
--- a/ui/accessibility/ax_role_properties.h
+++ b/ui/accessibility/ax_role_properties.h
@@ -20,10 +20,13 @@
 // https://www.w3.org/TR/wai-aria-1.1/#childrenArePresentational.
 AX_BASE_EXPORT bool HasPresentationalChildren(const ax::mojom::Role role);
 
-// Checks if the given role is an alert or alert-dialog type.
+// Returns if the given role is an alert or alert-dialog type.
 AX_BASE_EXPORT bool IsAlert(const ax::mojom::Role role);
 
-// Checks if the given role is a clickable type.
+// Returns if the given role is a native button or ARIA role="button".
+AX_BASE_EXPORT bool IsButton(const ax::mojom::Role role);
+
+// Returns if the given role is a clickable type.
 AX_BASE_EXPORT bool IsClickable(const ax::mojom::Role role);
 
 // Returns true if the provided role belongs to a cell or a table header.
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index 25b630b..6881b1b 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -1764,18 +1764,20 @@
 
 ExpandCollapseState AXPlatformNodeWin::ComputeExpandCollapseState() const {
   const AXNodeData& data = GetData();
-  const bool is_menu_button = data.GetHasPopup() == ax::mojom::HasPopup::kMenu;
-  const bool is_expanded_menu_button =
-      is_menu_button &&
-      data.GetCheckedState() == ax::mojom::CheckedState::kTrue;
-  const bool is_collapsed_menu_button =
-      is_menu_button &&
-      data.GetCheckedState() != ax::mojom::CheckedState::kTrue;
 
-  if (data.HasState(ax::mojom::State::kExpanded) || is_expanded_menu_button) {
+  // Since a menu button implies there is a popup and it is either expanded or
+  // collapsed, and it should not support ExpandCollapseState_LeafNode.
+  // According to the UIA spec, ExpandCollapseState_LeafNode indicates that the
+  // element neither expands nor collapses.
+  if (data.IsMenuButton()) {
+    if (data.IsButtonPressed())
+      return ExpandCollapseState_Expanded;
+    return ExpandCollapseState_Collapsed;
+  }
+
+  if (data.HasState(ax::mojom::State::kExpanded)) {
     return ExpandCollapseState_Expanded;
-  } else if (data.HasState(ax::mojom::State::kCollapsed) ||
-             is_collapsed_menu_button) {
+  } else if (data.HasState(ax::mojom::State::kCollapsed)) {
     return ExpandCollapseState_Collapsed;
   } else {
     return ExpandCollapseState_LeafNode;
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
index b635131b..1cbf2e81 100644
--- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -5558,6 +5558,7 @@
   ui::AXNodeData button_has_popup_menu;
   ui::AXNodeData button_has_popup_menu_pressed;
   ui::AXNodeData button_has_popup_true;
+  ui::AXNodeData generic_container_has_popup_menu;
 
   combo_box_grouping_has_popup.id = 2;
   combo_box_grouping_expanded.id = 3;
@@ -5566,14 +5567,13 @@
   button_has_popup_menu.id = 6;
   button_has_popup_menu_pressed.id = 7;
   button_has_popup_true.id = 8;
+  generic_container_has_popup_menu.id = 9;
 
-  root.child_ids.push_back(combo_box_grouping_has_popup.id);
-  root.child_ids.push_back(combo_box_grouping_expanded.id);
-  root.child_ids.push_back(combo_box_grouping_collapsed.id);
-  root.child_ids.push_back(combo_box_grouping_disabled.id);
-  root.child_ids.push_back(button_has_popup_menu.id);
-  root.child_ids.push_back(button_has_popup_menu_pressed.id);
-  root.child_ids.push_back(button_has_popup_true.id);
+  root.child_ids = {
+      combo_box_grouping_has_popup.id, combo_box_grouping_expanded.id,
+      combo_box_grouping_collapsed.id, combo_box_grouping_disabled.id,
+      button_has_popup_menu.id,        button_has_popup_menu_pressed.id,
+      button_has_popup_true.id,        generic_container_has_popup_menu.id};
 
   // combo_box_grouping HasPopup set to true, can collapse, can expand.
   // state is ExpandCollapseState_LeafNode.
@@ -5597,21 +5597,31 @@
 
   // button_has_popup_menu HasPopup set to kMenu and is not STATE_PRESSED.
   // state is ExpandCollapseState_Collapsed.
+  button_has_popup_menu.role = ax::mojom::Role::kButton;
   button_has_popup_menu.SetHasPopup(ax::mojom::HasPopup::kMenu);
 
   // button_has_popup_menu_pressed HasPopup set to kMenu and is STATE_PRESSED.
   // state is ExpandCollapseState_Expanded.
+  button_has_popup_menu_pressed.role = ax::mojom::Role::kButton;
   button_has_popup_menu_pressed.SetHasPopup(ax::mojom::HasPopup::kMenu);
   button_has_popup_menu_pressed.SetCheckedState(ax::mojom::CheckedState::kTrue);
 
   // button_has_popup_true HasPopup set to true but is not a menu.
   // state is ExpandCollapseState_LeafNode.
+  button_has_popup_true.role = ax::mojom::Role::kButton;
   button_has_popup_true.SetHasPopup(ax::mojom::HasPopup::kTrue);
 
+  // generic_container_has_popup_menu HasPopup set to menu but with no expand
+  // state set.
+  // state is ExpandCollapseState_LeafNode.
+  generic_container_has_popup_menu.role = ax::mojom::Role::kGenericContainer;
+  generic_container_has_popup_menu.SetHasPopup(ax::mojom::HasPopup::kMenu);
+
   Init(root, combo_box_grouping_has_popup, combo_box_grouping_disabled,
        combo_box_grouping_expanded, combo_box_grouping_collapsed,
        combo_box_grouping_disabled, button_has_popup_menu,
-       button_has_popup_menu_pressed, button_has_popup_true);
+       button_has_popup_menu_pressed, button_has_popup_true,
+       generic_container_has_popup_menu);
 
   // combo_box_grouping HasPopup set to true, can collapse, can expand.
   // state is ExpandCollapseState_LeafNode.
@@ -5620,7 +5630,7 @@
   ComPtr<IExpandCollapseProvider> expandcollapse_provider;
   EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
       UIA_ExpandCollapsePatternId, &expandcollapse_provider));
-  EXPECT_NE(nullptr, expandcollapse_provider.Get());
+  ASSERT_NE(nullptr, expandcollapse_provider.Get());
   EXPECT_HRESULT_SUCCEEDED(expandcollapse_provider->Collapse());
   EXPECT_HRESULT_SUCCEEDED(expandcollapse_provider->Expand());
   ExpandCollapseState state;
@@ -5633,7 +5643,7 @@
   raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(1);
   EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
       UIA_ExpandCollapsePatternId, &expandcollapse_provider));
-  EXPECT_NE(nullptr, expandcollapse_provider.Get());
+  ASSERT_NE(nullptr, expandcollapse_provider.Get());
   EXPECT_HRESULT_SUCCEEDED(expandcollapse_provider->Collapse());
   EXPECT_HRESULT_FAILED(expandcollapse_provider->Expand());
   EXPECT_HRESULT_SUCCEEDED(
@@ -5645,7 +5655,7 @@
   raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(2);
   EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
       UIA_ExpandCollapsePatternId, &expandcollapse_provider));
-  EXPECT_NE(nullptr, expandcollapse_provider.Get());
+  ASSERT_NE(nullptr, expandcollapse_provider.Get());
   EXPECT_HRESULT_FAILED(expandcollapse_provider->Collapse());
   EXPECT_HRESULT_SUCCEEDED(expandcollapse_provider->Expand());
   EXPECT_HRESULT_SUCCEEDED(
@@ -5657,7 +5667,7 @@
   raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(3);
   EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
       UIA_ExpandCollapsePatternId, &expandcollapse_provider));
-  EXPECT_NE(nullptr, expandcollapse_provider.Get());
+  ASSERT_NE(nullptr, expandcollapse_provider.Get());
   EXPECT_HRESULT_FAILED(expandcollapse_provider->Collapse());
   EXPECT_HRESULT_FAILED(expandcollapse_provider->Expand());
   EXPECT_HRESULT_SUCCEEDED(
@@ -5669,7 +5679,7 @@
   raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(4);
   EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
       UIA_ExpandCollapsePatternId, &expandcollapse_provider));
-  EXPECT_NE(nullptr, expandcollapse_provider.Get());
+  ASSERT_NE(nullptr, expandcollapse_provider.Get());
   EXPECT_HRESULT_SUCCEEDED(
       expandcollapse_provider->get_ExpandCollapseState(&state));
   EXPECT_EQ(ExpandCollapseState_Collapsed, state);
@@ -5679,7 +5689,7 @@
   raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(5);
   EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
       UIA_ExpandCollapsePatternId, &expandcollapse_provider));
-  EXPECT_NE(nullptr, expandcollapse_provider.Get());
+  ASSERT_NE(nullptr, expandcollapse_provider.Get());
   EXPECT_HRESULT_SUCCEEDED(
       expandcollapse_provider->get_ExpandCollapseState(&state));
   EXPECT_EQ(ExpandCollapseState_Expanded, state);
@@ -5689,7 +5699,18 @@
   raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(6);
   EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
       UIA_ExpandCollapsePatternId, &expandcollapse_provider));
-  EXPECT_NE(nullptr, expandcollapse_provider.Get());
+  ASSERT_NE(nullptr, expandcollapse_provider.Get());
+  EXPECT_HRESULT_SUCCEEDED(
+      expandcollapse_provider->get_ExpandCollapseState(&state));
+  EXPECT_EQ(ExpandCollapseState_LeafNode, state);
+
+  // generic_container_has_popup_menu HasPopup set to menu but with no expand
+  // state set.
+  // state is ExpandCollapseState_LeafNode.
+  raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(7);
+  EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
+      UIA_ExpandCollapsePatternId, &expandcollapse_provider));
+  ASSERT_NE(nullptr, expandcollapse_provider.Get());
   EXPECT_HRESULT_SUCCEEDED(
       expandcollapse_provider->get_ExpandCollapseState(&state));
   EXPECT_EQ(ExpandCollapseState_LeafNode, state);
diff --git a/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js b/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js
index 71c4c40f..06e0ae9 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js
@@ -340,6 +340,18 @@
   }
 
   /**
+   * Returns breadcrumb buttons that have a 'has-tooltip' attribute. Note the
+   * elider button is excluded since it has an i18n aria-label.
+   *
+   * @return {!Array<HTMLButtonElement>} buttons Caller could remove the tool
+   *    tip event listeners from the returned buttons.
+   */
+  getToolTipButtons() {
+    const hasToolTip = 'button:not([elider])[has-tooltip]';
+    return Array.from(this.shadowRoot.querySelectorAll(hasToolTip));
+  }
+
+  /**
    * Handles 'click' events.
    *
    * Emits an index signal on breadcumb button click: the index indicates the
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/GeolocationTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/GeolocationTest.java
index 541baa09..34f9b89 100644
--- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/GeolocationTest.java
+++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/GeolocationTest.java
@@ -5,7 +5,6 @@
 package org.chromium.weblayer.test;
 
 import android.net.Uri;
-import android.os.Bundle;
 import android.support.test.filters.MediumTest;
 
 import org.junit.After;
@@ -67,14 +66,11 @@
 
     @Before
     public void setUp() throws Throwable {
-        Bundle extras = new Bundle();
-        // TODO(crbug.com/1064500): If this prevents flakes figure out why preferences are getting
-        // persisted across test runs for non-incognito profiles.
-        extras.putString(InstrumentationActivity.EXTRA_PROFILE_NAME, null);
-        mActivity = mActivityTestRule.launchShellWithUrl("about:blank", extras);
+        mActivity = mActivityTestRule.launchShellWithUrl("about:blank");
         Assert.assertNotNull(mActivity);
 
         mTestWebLayer = TestWebLayer.getTestWebLayer(mActivity.getApplicationContext());
+        mTestWebLayer.setSystemLocationSettingEnabled(true);
         mTestWebLayer.setMockLocationProvider(true /* enable */);
 
         mTestServer = TestWebServer.start();
diff --git a/weblayer/browser/java/DEPS b/weblayer/browser/java/DEPS
index 147a1e8..3415f3d 100644
--- a/weblayer/browser/java/DEPS
+++ b/weblayer/browser/java/DEPS
@@ -2,6 +2,7 @@
   "+components/browser_ui/util/android",
   "+components/crash/android/java",
   "+components/external_intents",
+  "+components/location/android/java/src/org/chromium/components/location",
   "+components/minidump_uploader",
   "+services/device/public/java/src/org/chromium/device/geolocation",
 ]
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/test/TestWebLayerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/test/TestWebLayerImpl.java
index 9b6c3b0..e4502811 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/test/TestWebLayerImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/test/TestWebLayerImpl.java
@@ -7,6 +7,7 @@
 import android.os.IBinder;
 
 import org.chromium.base.annotations.UsedByReflection;
+import org.chromium.components.location.LocationUtils;
 import org.chromium.components.permissions.PermissionDialogController;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.device.geolocation.LocationProviderOverrider;
@@ -71,4 +72,18 @@
                             : ModalDialogProperties.ButtonType.NEGATIVE);
         });
     }
+
+    @Override
+    public void setSystemLocationSettingEnabled(boolean enabled) {
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            LocationUtils.setFactory(() -> {
+                return new LocationUtils() {
+                    @Override
+                    public boolean isSystemLocationSettingEnabled() {
+                        return enabled;
+                    }
+                };
+            });
+        });
+    }
 }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/ITestWebLayer.aidl b/weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/ITestWebLayer.aidl
index 7000fdc..3664df20 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/ITestWebLayer.aidl
+++ b/weblayer/browser/java/org/chromium/weblayer_private/test_interfaces/ITestWebLayer.aidl
@@ -15,5 +15,8 @@
   boolean isPermissionDialogShown() = 4;
 
   // Clicks a button on the permission dialog.
-  void clickPermissionDialogButton(in boolean allow) = 5;
+  void clickPermissionDialogButton(boolean allow) = 5;
+
+  // Forces the system location setting to enabled.
+  void setSystemLocationSettingEnabled(boolean enabled) = 6;
 }
diff --git a/weblayer/browser/safe_browsing/safe_browsing_service.cc b/weblayer/browser/safe_browsing/safe_browsing_service.cc
index 29397c1..7e3a7472 100644
--- a/weblayer/browser/safe_browsing/safe_browsing_service.cc
+++ b/weblayer/browser/safe_browsing/safe_browsing_service.cc
@@ -34,6 +34,28 @@
   return network_context_params;
 }
 
+// Helper method that checks the RenderProcessHost is still alive before hopping
+// over to the IO thread.
+void MaybeCreateSafeBrowsing(
+    int rph_id,
+    content::ResourceContext* resource_context,
+    base::RepeatingCallback<scoped_refptr<safe_browsing::UrlCheckerDelegate>()>
+        get_checker_delegate,
+    mojo::PendingReceiver<safe_browsing::mojom::SafeBrowsing> receiver) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  content::RenderProcessHost* render_process_host =
+      content::RenderProcessHost::FromID(rph_id);
+  if (!render_process_host)
+    return;
+
+  base::PostTask(
+      FROM_HERE, {content::BrowserThread::IO},
+      base::BindOnce(&safe_browsing::MojoSafeBrowsingImpl::MaybeCreate, rph_id,
+                     resource_context, std::move(get_checker_delegate),
+                     std::move(receiver)));
+}
+
 }  // namespace
 
 SafeBrowsingService::SafeBrowsingService(const std::string& user_agent)
@@ -170,12 +192,12 @@
       render_process_host->GetBrowserContext()->GetResourceContext();
   registry->AddInterface(
       base::BindRepeating(
-          &safe_browsing::MojoSafeBrowsingImpl::MaybeCreate,
-          render_process_host->GetID(), resource_context,
+          &MaybeCreateSafeBrowsing, render_process_host->GetID(),
+          resource_context,
           base::BindRepeating(
               &SafeBrowsingService::GetSafeBrowsingUrlCheckerDelegate,
               base::Unretained(this))),
-      base::CreateSingleThreadTaskRunner({content::BrowserThread::IO}));
+      base::CreateSingleThreadTaskRunner({content::BrowserThread::UI}));
 }
 
 }  // namespace weblayer
diff --git a/weblayer/public/javatestutil/org/chromium/weblayer/TestWebLayer.java b/weblayer/public/javatestutil/org/chromium/weblayer/TestWebLayer.java
index 4e0126e..370103f4 100644
--- a/weblayer/public/javatestutil/org/chromium/weblayer/TestWebLayer.java
+++ b/weblayer/public/javatestutil/org/chromium/weblayer/TestWebLayer.java
@@ -71,4 +71,8 @@
     public void clickPermissionDialogButton(boolean allow) throws RemoteException {
         mITestWebLayer.clickPermissionDialogButton(allow);
     }
+
+    public void setSystemLocationSettingEnabled(boolean enabled) throws RemoteException {
+        mITestWebLayer.setSystemLocationSettingEnabled(enabled);
+    }
 }