diff --git a/BUILD.gn b/BUILD.gn
index b683de2..6992a98 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -264,9 +264,9 @@
       ":d8_fuchsia",
       "//build/fuchsia/cipd",
       "//fuchsia/engine:web_engine",
-      "//fuchsia/release:fuchsia_sizes",
       "//fuchsia/runners:cast_runner",
       "//fuchsia/runners:web_runner",
+      "//tools/fuchsia/size_tests:fuchsia_sizes",
 
       # Ensure this target, used by cipd, is built in all configurations.
       # TODO(crbug.com/1265618): Remove this once it has a natural dependency.
diff --git a/DEPS b/DEPS
index 4dc7e9f..9f95a75 100644
--- a/DEPS
+++ b/DEPS
@@ -269,15 +269,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'e1df5b2115b302a0cabeb1f117119a42a962079c',
+  'skia_revision': 'faa99cb9314f9d14da7aa4e0f396987db66a49ee',
   # 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': '15839b80b06f986b4a638a26656cee97646e9071',
+  'v8_revision': '1a8f4cab47232e7861928945eeee1c40fe7f7c08',
   # 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': '5b623dd4b871c37590f4aaaa07dacf8b736ab7c7',
+  'angle_revision': 'dd9b4afe5645890638655a740fb9fe381a663779',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -348,7 +348,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': 'b6327d5184fe4304683b3fd756f0d7bcaf497fb0',
+  'devtools_frontend_revision': 'f2ac64a53ae43422c6d8ee1f74174db4bbb13d57',
   # 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.
@@ -384,7 +384,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': '6a8cfd4153c5d47b8dc3293f504b1254b6bbef19',
+  'dawn_revision': '75a31aa10aa6767d6dd1906568b93345b3c16bb9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -428,7 +428,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.
-  'libcxxabi_revision':    'ecff200716d0e23f46d01dfcebac61ac7e00b15b',
+  'libcxxabi_revision':    'bb1e46cb72b89a8bb61cc16ad33267b53889aae3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -835,7 +835,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/linux-amd64',
-          'version': 'BYhBwKD_mQiXI07HLtMbq9rvpsXCcxZ_GxLQ8x_i1xgC',
+          'version': 'KZbOWyGl41EX1PlJ5EkkQ7uXgfbDU5_jgwuBfzWAU-EC',
         },
       ],
       'dep_type': 'cipd',
@@ -846,7 +846,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/mac-amd64',
-          'version': 'm09GIAiaD-5EvhXkbqkTvXyxDhemj8SS74LKiFad2uQC',
+          'version': 'VeBGWNvPjjvuUBd78PYxm9BBVGYOLdVeAAdaBscZAdAC',
         },
       ],
       'dep_type': 'cipd',
@@ -857,7 +857,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/windows-amd64',
-          'version': 'iisJyZQ2Qc0Hti6gD7K1QgX3Fx9yRfh2eyxoOwAG4-gC',
+          'version': 'K6xgV4tqvjNfCU66sz6WMgX80oGWTUZwRkp9OH5j_UIC',
         },
       ],
       'dep_type': 'cipd',
@@ -914,7 +914,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': '9EARqDo1HNj2IE6F5pbKWOUSN2acBpBu04AW3SP7qAEC',
+          'version': '2V7ZDLIKJDlBnGSSJXQDu9ZmBIHGqJzUGaNLc9A8nkoC',
       },
     ],
     'condition': 'checkout_android',
@@ -1107,7 +1107,7 @@
   # Tools used when building Chrome for Chrome OS. This affects both the Simple
   # Chrome workflow, as well as the chromeos-chrome ebuild.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '51d6d4f13068ae5f986bec25ff1b951691f8febf',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'e332c78c2b9ee73b657c6b13fedcd908b37f6ffe',
       'condition': 'checkout_chromeos',
   },
 
@@ -1527,7 +1527,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '1de2530cbbe478a28578869e82d2bee70db0396c',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '478630351306440b9bfb971ee7914704fecacd75',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1663,7 +1663,7 @@
       'condition': 'checkout_android',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@b768d03422eaba0e33c6ed6aaf12f04e5ec0ea2b',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@3e76ffe3d4b39f7ec38581712dbde5c2e63ef0fb',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1775,7 +1775,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e82224de6bc39a4ce9ed47ccb0b719ddc585ecaf',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@070bf9de22add8973cbef0e81336da9463d7397b',
     'condition': 'checkout_src_internal',
   },
 
@@ -1805,7 +1805,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'WE2dNk7PzsVwggpmYGtw6BzkX1c7urdcSQnXzS5HyzMC',
+        'version': 'AajffdMk1aTPJcI58zxg_IIXWAnJIQeXYEnkOZl6ANYC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1816,7 +1816,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'IeHZKglM4cQ33E3dEoq-oKBor4jfE69BSSL5tx7XNv0C',
+        'version': 'WteMeuSUMJqpnMC5LMl5BWJGfjosmnhFQbIqa7QKKhkC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/WATCHLISTS b/WATCHLISTS
index 05f2e73f..4a782a7f 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -2155,7 +2155,7 @@
     'android_studio': ['wnwen+watch@chromium.org',
                        'nyquist+watch@chromium.org'],
     'android_tab': ['dtrainor+watch@chromium.org'],
-    'android_toolbar': ['hanxi+watch@chromium.org'],
+    'android_toolbar': ['hanxi+watch@chromium.org', 'spdonghao+watch@chromium.org'],
     'android_toolbar_deps': ['jinsukkim+watch@chromium.org'],
     'android_uma_settings': ['asvitkine+watch@chromium.org',
                              'gayane+watch@chromium.org'],
@@ -2841,7 +2841,8 @@
                                  'gogerald+watch@chromium.org',
                                  'hanxi+watch@chromium.org',
                                  'mattsimmons+watch@chromium.org',
-                                 'davidjm+watch@chromium.org'],
+                                 'davidjm+watch@chromium.org',
+                                 'spdonghao+watch@chromium.org'],
     'tbmv2_metrics': ['speed-metrics-reviews@chromium.org'],
     'telemetry': ['telemetry-reviews@chromium.org'],
     'test_runner': ['einbinder+watch-test-runner@chromium.org'],
diff --git a/android_webview/browser/aw_permission_manager.cc b/android_webview/browser/aw_permission_manager.cc
index f0d6a4b..d0ddf34 100644
--- a/android_webview/browser/aw_permission_manager.cc
+++ b/android_webview/browser/aw_permission_manager.cc
@@ -441,6 +441,17 @@
   result_cache_->ClearResult(permission, requesting_origin, embedding_origin);
 }
 
+void AwPermissionManager::RequestPermissionsFromCurrentDocument(
+    const std::vector<PermissionType>& permissions,
+    content::RenderFrameHost* render_frame_host,
+    bool user_gesture,
+    base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
+        callback) {
+  RequestPermissions(permissions, render_frame_host,
+                     LastCommittedOrigin(render_frame_host), user_gesture,
+                     std::move(callback));
+}
+
 PermissionStatus AwPermissionManager::GetPermissionStatus(
     PermissionType permission,
     const GURL& requesting_origin,
@@ -457,23 +468,15 @@
   return PermissionStatus::DENIED;
 }
 
-PermissionStatus AwPermissionManager::GetPermissionStatusForFrame(
-    PermissionType permission,
-    content::RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin) {
-  return GetPermissionStatus(
-      permission, requesting_origin,
-      permissions::PermissionUtil::GetLastCommittedOriginAsURL(
-          render_frame_host));
-}
-
 PermissionStatus AwPermissionManager::GetPermissionStatusForCurrentDocument(
     PermissionType permission,
     content::RenderFrameHost* render_frame_host) {
   return GetPermissionStatus(
-      permission, render_frame_host->GetLastCommittedOrigin().GetURL(),
+      permission,
       permissions::PermissionUtil::GetLastCommittedOriginAsURL(
-          render_frame_host));
+          render_frame_host),
+      permissions::PermissionUtil::GetLastCommittedOriginAsURL(
+          render_frame_host->GetMainFrame()));
 }
 
 PermissionStatus AwPermissionManager::GetPermissionStatusForWorker(
diff --git a/android_webview/browser/aw_permission_manager.h b/android_webview/browser/aw_permission_manager.h
index ce30c1d..9713d7a 100644
--- a/android_webview/browser/aw_permission_manager.h
+++ b/android_webview/browser/aw_permission_manager.h
@@ -49,14 +49,17 @@
   void ResetPermission(blink::PermissionType permission,
                        const GURL& requesting_origin,
                        const GURL& embedding_origin) override;
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<
+          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+      override;
   blink::mojom::PermissionStatus GetPermissionStatus(
       blink::PermissionType permission,
       const GURL& requesting_origin,
       const GURL& embedding_origin) override;
-  blink::mojom::PermissionStatus GetPermissionStatusForFrame(
-      blink::PermissionType permission,
-      content::RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin) override;
   blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
       blink::PermissionType permission,
       content::RenderFrameHost* render_frame_host) override;
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index b54a6295..c5570549 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1843,8 +1843,6 @@
     "wm/desks/scroll_arrow_button.h",
     "wm/desks/templates/desks_templates_metrics_util.cc",
     "wm/desks/templates/desks_templates_metrics_util.h",
-    "wm/desks/templates/desks_templates_presenter.cc",
-    "wm/desks/templates/desks_templates_presenter.h",
     "wm/desks/templates/restore_data_collector.cc",
     "wm/desks/templates/restore_data_collector.h",
     "wm/desks/templates/save_desk_template_button.cc",
@@ -1867,6 +1865,8 @@
     "wm/desks/templates/saved_desk_library_view.h",
     "wm/desks/templates/saved_desk_name_view.cc",
     "wm/desks/templates/saved_desk_name_view.h",
+    "wm/desks/templates/saved_desk_presenter.cc",
+    "wm/desks/templates/saved_desk_presenter.h",
     "wm/desks/templates/saved_desk_util.cc",
     "wm/desks/templates/saved_desk_util.h",
     "wm/desks/zero_state_button.cc",
diff --git a/ash/app_list/app_list_presenter_unittest.cc b/ash/app_list/app_list_presenter_unittest.cc
index 10fb4988..c65b9cf 100644
--- a/ash/app_list/app_list_presenter_unittest.cc
+++ b/ash/app_list/app_list_presenter_unittest.cc
@@ -496,25 +496,29 @@
   }
 
   void CancelSearchResultPageDialog() {
-    views::WidgetDelegate* widget_delegate =
-        GetSearchResultPageDialog()->widget()->widget_delegate();
+    views::Widget* widget = GetSearchResultPageDialog()->widget();
+    views::WidgetDelegate* widget_delegate = widget->widget_delegate();
+    views::test::WidgetDestroyedWaiter widget_waiter(widget);
     if (!productivity_launcher_param()) {
       widget_delegate->AsDialogDelegate()->CancelDialog();
     } else {
       GestureTapOn(static_cast<RemoveQueryConfirmationDialog*>(widget_delegate)
                        ->cancel_button_for_test());
     }
+    widget_waiter.Wait();
   }
 
   void AcceptSearchResultPageDialog() {
-    views::WidgetDelegate* widget_delegate =
-        GetSearchResultPageDialog()->widget()->widget_delegate();
+    views::Widget* widget = GetSearchResultPageDialog()->widget();
+    views::WidgetDelegate* widget_delegate = widget->widget_delegate();
+    views::test::WidgetDestroyedWaiter widget_waiter(widget);
     if (!productivity_launcher_param()) {
       widget_delegate->AsDialogDelegate()->AcceptDialog();
     } else {
       GestureTapOn(static_cast<RemoveQueryConfirmationDialog*>(widget_delegate)
                        ->accept_button_for_test());
     }
+    widget_waiter.Wait();
   }
 
   ContinueSectionView* GetContinueSectionView() {
diff --git a/ash/app_list/views/continue_section_view_unittest.cc b/ash/app_list/views/continue_section_view_unittest.cc
index 16e4f4f6..e68f213 100644
--- a/ash/app_list/views/continue_section_view_unittest.cc
+++ b/ash/app_list/views/continue_section_view_unittest.cc
@@ -309,6 +309,11 @@
     return GetAppListTestHelper()->GetBubbleSearchPageDialog();
   }
 
+  bool IsSearchViewAnchoredDialogOpen() {
+    SearchResultPageAnchoredDialog* dialog = GetSearchViewAnchoredDialog();
+    return (dialog && !dialog->widget()->IsClosed());
+  }
+
   RemoveTaskFeedbackDialog* GetFeedbackDialog() {
     SearchResultPageAnchoredDialog* dialog = GetSearchViewAnchoredDialog();
     return dialog ? static_cast<RemoveTaskFeedbackDialog*>(
@@ -798,11 +803,11 @@
   EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1");
   RemoveSearchResultWithContextMenuAt(0);
 
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   ASSERT_TRUE(GetFeedbackDialog());
   GestureTapOn(GetFeedbackDialog()->cancel_button_for_test());
 
-  EXPECT_FALSE(GetSearchViewAnchoredDialog());
+  EXPECT_FALSE(IsSearchViewAnchoredDialogOpen());
 
   TestAppListClient* client = GetAppListTestHelper()->app_list_client();
   std::vector<TestAppListClient::SearchResultActionId> invoked_actions =
@@ -822,11 +827,11 @@
   EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1");
   RemoveSearchResultWithContextMenuAt(0);
 
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   ASSERT_TRUE(GetFeedbackDialog());
   GestureTapOn(GetFeedbackDialog()->remove_button_for_test());
 
-  EXPECT_FALSE(GetSearchViewAnchoredDialog());
+  EXPECT_FALSE(IsSearchViewAnchoredDialogOpen());
 
   TestAppListClient* client = GetAppListTestHelper()->app_list_client();
   std::vector<TestAppListClient::SearchResultActionId> expected_actions = {
@@ -849,13 +854,13 @@
   EXPECT_EQ(GetResultViewAt(1)->result()->id(), "id2");
   RemoveSearchResultWithContextMenuAt(1);
 
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog();
   ASSERT_TRUE(dialog);
   GestureTapOn(dialog->all_suggestions_option_for_test());
   GestureTapOn(dialog->remove_button_for_test());
 
-  EXPECT_FALSE(GetSearchViewAnchoredDialog());
+  EXPECT_FALSE(IsSearchViewAnchoredDialogOpen());
 
   VerifyResultViewsUpdated();
 
@@ -864,7 +869,7 @@
   RemoveSearchResultWithContextMenuAt(0);
 
   // Feedback Dialog should not show the second time.
-  EXPECT_FALSE(GetSearchViewAnchoredDialog());
+  EXPECT_FALSE(IsSearchViewAnchoredDialogOpen());
 
   // Both items were removed.
   TestAppListClient* client = GetAppListTestHelper()->app_list_client();
@@ -890,12 +895,12 @@
   RemoveSearchResultWithContextMenuAt(1);
 
   // Feedback dialog should show. Confirm without sending feedback.
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog();
   ASSERT_TRUE(dialog);
   GestureTapOn(dialog->remove_button_for_test());
 
-  EXPECT_FALSE(GetSearchViewAnchoredDialog());
+  EXPECT_FALSE(IsSearchViewAnchoredDialogOpen());
 
   VerifyResultViewsUpdated();
 
@@ -904,13 +909,13 @@
   RemoveSearchResultWithContextMenuAt(0);
 
   // Feedback Dialog should show a second time. Send feedback.
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   dialog = GetFeedbackDialog();
   ASSERT_TRUE(dialog);
   GestureTapOn(dialog->all_suggestions_option_for_test());
   GestureTapOn(dialog->remove_button_for_test());
 
-  EXPECT_FALSE(GetSearchViewAnchoredDialog());
+  EXPECT_FALSE(IsSearchViewAnchoredDialogOpen());
 
   VerifyResultViewsUpdated();
 
@@ -919,7 +924,7 @@
   RemoveSearchResultWithContextMenuAt(2);
 
   // Feedback Dialog should not show.
-  EXPECT_FALSE(GetSearchViewAnchoredDialog());
+  EXPECT_FALSE(IsSearchViewAnchoredDialogOpen());
 
   // Both items were removed.
   TestAppListClient* client = GetAppListTestHelper()->app_list_client();
@@ -947,18 +952,18 @@
   RemoveSearchResultWithContextMenuAt(1);
 
   // Cancel the Feedback Dialog, result should not have been removed.
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   ASSERT_TRUE(GetFeedbackDialog());
   GestureTapOn(GetFeedbackDialog()->cancel_button_for_test());
 
-  EXPECT_FALSE(GetSearchViewAnchoredDialog());
+  EXPECT_FALSE(IsSearchViewAnchoredDialogOpen());
   VerifyResultViewsUpdated();
 
   EXPECT_EQ(GetResultViewAt(1)->result()->id(), "id2");
   RemoveSearchResultWithContextMenuAt(1);
 
   // Feedback Dialog should show again.
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   ASSERT_TRUE(GetFeedbackDialog());
   GestureTapOn(GetFeedbackDialog()->remove_button_for_test());
 
@@ -983,7 +988,7 @@
   EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1");
   RemoveSearchResultWithContextMenuAt(0);
 
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog();
   ASSERT_TRUE(dialog);
   EXPECT_FALSE(dialog->secondary_options_panel_for_test()->GetVisible());
@@ -1002,7 +1007,7 @@
   EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1");
   RemoveSearchResultWithContextMenuAt(0);
 
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog();
   ASSERT_TRUE(dialog);
 
@@ -1024,7 +1029,7 @@
   EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1");
   RemoveSearchResultWithContextMenuAt(0);
 
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog();
   ASSERT_TRUE(dialog);
 
@@ -1049,7 +1054,7 @@
   EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1");
   RemoveSearchResultWithContextMenuAt(0);
 
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   ASSERT_TRUE(GetFeedbackDialog());
   GestureTapOn(GetFeedbackDialog()->remove_button_for_test());
 
@@ -1076,7 +1081,7 @@
   EXPECT_EQ(GetResultViewAt(0)->result()->id(), "id1");
   RemoveSearchResultWithContextMenuAt(0);
 
-  ASSERT_TRUE(GetSearchViewAnchoredDialog());
+  ASSERT_TRUE(IsSearchViewAnchoredDialogOpen());
   RemoveTaskFeedbackDialog* dialog = GetFeedbackDialog();
   ASSERT_TRUE(dialog);
   GestureTapOn(dialog->all_suggestions_option_for_test());
@@ -1085,7 +1090,7 @@
   EXPECT_EQ(GetResultViewAt(1)->result()->id(), "id2");
   RemoveSearchResultWithContextMenuAt(1);
 
-  ASSERT_FALSE(GetSearchViewAnchoredDialog());
+  ASSERT_FALSE(IsSearchViewAnchoredDialogOpen());
 
   TestAppListClient* client = GetAppListTestHelper()->app_list_client();
   std::vector<TestAppListClient::SearchResultActionId> expected_actions = {
diff --git a/ash/app_list/views/search_result_page_anchored_dialog.cc b/ash/app_list/views/search_result_page_anchored_dialog.cc
index d7f9ff1..228a084 100644
--- a/ash/app_list/views/search_result_page_anchored_dialog.cc
+++ b/ash/app_list/views/search_result_page_anchored_dialog.cc
@@ -97,13 +97,6 @@
   return default_offset + parent_offset;
 }
 
-void SearchResultPageAnchoredDialog::OnWidgetClosing(views::Widget* widget) {
-  widget_ = nullptr;
-  widget_observations_.RemoveAllObservations();
-  if (callback_)
-    std::move(callback_).Run();
-}
-
 void SearchResultPageAnchoredDialog::OnWidgetDestroying(views::Widget* widget) {
   widget_ = nullptr;
   widget_observations_.RemoveAllObservations();
diff --git a/ash/app_list/views/search_result_page_anchored_dialog.h b/ash/app_list/views/search_result_page_anchored_dialog.h
index 942d28f..bdb8671 100644
--- a/ash/app_list/views/search_result_page_anchored_dialog.h
+++ b/ash/app_list/views/search_result_page_anchored_dialog.h
@@ -55,7 +55,6 @@
   float AdjustVerticalTransformOffset(float default_offset);
 
   // views::WidgetObserver:
-  void OnWidgetClosing(views::Widget* widget) override;
   void OnWidgetDestroying(views::Widget* widget) override;
   void OnWidgetBoundsChanged(views::Widget* widget,
                              const gfx::Rect& new_bounds) override;
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 09d7eaa..872845ab 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -3467,10 +3467,18 @@
         Show previous month
       </message>
 
+      <message name="IDS_ASH_CALENDAR_UP_BUTTON_EVENT_LIST_ACCESSIBLE_DESCRIPTION" desc="The accessible/tooltip description of the calendar up button in the event list mode.">
+        Show previous week
+      </message>
+
       <message name="IDS_ASH_CALENDAR_DOWN_BUTTON_ACCESSIBLE_DESCRIPTION" desc="The accessible/tooltip description of the calendar down button.">
         Show next month
       </message>
 
+      <message name="IDS_ASH_CALENDAR_DOWN_BUTTON_EVENT_LIST_ACCESSIBLE_DESCRIPTION" desc="The accessible/tooltip description of the calendar down button in the event list mode.">
+        Show next week
+      </message>
+
       <message name="IDS_ASH_CALENDAR_INFO_BUTTON_ACCESSIBLE_DESCRIPTION" desc="The accessible description of the calendar today's button.">
         Today <ph name="today_date">$1<ex>August 31, 2021</ex></ph>
       </message>
diff --git a/ash/ash_strings_grd/IDS_ASH_CALENDAR_DOWN_BUTTON_EVENT_LIST_ACCESSIBLE_DESCRIPTION.png.sha1 b/ash/ash_strings_grd/IDS_ASH_CALENDAR_DOWN_BUTTON_EVENT_LIST_ACCESSIBLE_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..6bbfae66
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_CALENDAR_DOWN_BUTTON_EVENT_LIST_ACCESSIBLE_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+3f1c3372440ef89ae3ae2fc41fe4d915a96ec0e1
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_CALENDAR_UP_BUTTON_EVENT_LIST_ACCESSIBLE_DESCRIPTION.png.sha1 b/ash/ash_strings_grd/IDS_ASH_CALENDAR_UP_BUTTON_EVENT_LIST_ACCESSIBLE_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..17776d8
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_CALENDAR_UP_BUTTON_EVENT_LIST_ACCESSIBLE_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+150e80472525c2ec525f7dc77104116d7bee32f0
\ No newline at end of file
diff --git a/ash/capture_mode/capture_mode_camera_unittests.cc b/ash/capture_mode/capture_mode_camera_unittests.cc
index 7311a319..2ee3450c 100644
--- a/ash/capture_mode/capture_mode_camera_unittests.cc
+++ b/ash/capture_mode/capture_mode_camera_unittests.cc
@@ -373,7 +373,6 @@
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
-  base::SystemMonitor system_monitor_;
   std::unique_ptr<aura::Window> window_;
 };
 
diff --git a/ash/capture_mode/capture_mode_menu_group.cc b/ash/capture_mode/capture_mode_menu_group.cc
index a0da31ce..fc685e8 100644
--- a/ash/capture_mode/capture_mode_menu_group.cc
+++ b/ash/capture_mode/capture_mode_menu_group.cc
@@ -372,6 +372,11 @@
 void CaptureModeMenuGroup::AppendHighlightableItems(
     std::vector<CaptureModeSessionFocusCycler::HighlightableView*>&
         highlightable_items) {
+  // The camera menu group can be hidden if there are no cameras connected. In
+  // this case no items in this group should be highlightable.
+  if (!GetVisible())
+    return;
+
   highlightable_items.push_back(menu_header_);
   for (auto* option : options_) {
     if (option->GetEnabled())
diff --git a/ash/components/hid_detection/bluetooth_hid_detector.cc b/ash/components/hid_detection/bluetooth_hid_detector.cc
index 4e4bd07..bf5c9d91 100644
--- a/ash/components/hid_detection/bluetooth_hid_detector.cc
+++ b/ash/components/hid_detection/bluetooth_hid_detector.cc
@@ -78,5 +78,23 @@
 
 BluetoothHidDetector::~BluetoothHidDetector() = default;
 
+void BluetoothHidDetector::StartBluetoothHidDetection(
+    Delegate* delegate,
+    InputDevicesStatus input_devices_status) {
+  DCHECK(!delegate_);
+  delegate_ = delegate;
+  PerformStartBluetoothHidDetection(input_devices_status);
+}
+
+void BluetoothHidDetector::StopBluetoothHidDetection() {
+  DCHECK(delegate_);
+  PerformStopBluetoothHidDetection();
+  delegate_ = nullptr;
+}
+
+void BluetoothHidDetector::NotifyBluetoothHidDetectionStatusChanged() {
+  delegate_->OnBluetoothHidStatusChanged();
+}
+
 }  // namespace hid_detection
 }  // namespace ash
diff --git a/ash/components/hid_detection/bluetooth_hid_detector.h b/ash/components/hid_detection/bluetooth_hid_detector.h
index 1518605..f74f7b0 100644
--- a/ash/components/hid_detection/bluetooth_hid_detector.h
+++ b/ash/components/hid_detection/bluetooth_hid_detector.h
@@ -86,13 +86,12 @@
   // OnBluetoothHidStatusChanged() for |delegate| whenever the HID detection
   // status updates. Calling this method when HID detection has already started
   // is an error.
-  virtual void StartBluetoothHidDetection(
-      Delegate* delegate,
-      InputDevicesStatus input_devices_status) = 0;
+  void StartBluetoothHidDetection(Delegate* delegate,
+                                  InputDevicesStatus input_devices_status);
 
   // Stops scanning for Bluetooth devices. Calling this method when HID
   // detection has not been started is an error.
-  virtual void StopBluetoothHidDetection() = 0;
+  void StopBluetoothHidDetection();
 
   // Informs BluetoothHidDetector which HID types have been connected.
   virtual void SetInputDevicesStatus(
@@ -104,6 +103,20 @@
 
  protected:
   BluetoothHidDetector();
+
+  // Implementation-specific version of StartBluetoothHidDetection().
+  virtual void PerformStartBluetoothHidDetection(
+      InputDevicesStatus input_devices_status) = 0;
+
+  // Implementation-specific version of StopBluetoothHidDetection().
+  virtual void PerformStopBluetoothHidDetection() = 0;
+
+  // Notifies |delegate_| of status changes; should be called by derived
+  // types to notify observers of status changes.
+  void NotifyBluetoothHidDetectionStatusChanged();
+
+ private:
+  Delegate* delegate_ = nullptr;
 };
 
 }  // namespace hid_detection
diff --git a/ash/components/hid_detection/bluetooth_hid_detector_impl.cc b/ash/components/hid_detection/bluetooth_hid_detector_impl.cc
index e3cf911..0323bbcd 100644
--- a/ash/components/hid_detection/bluetooth_hid_detector_impl.cc
+++ b/ash/components/hid_detection/bluetooth_hid_detector_impl.cc
@@ -43,40 +43,6 @@
                                  << "BluetoothHidDetectorImpl is destroyed.";
 }
 
-void BluetoothHidDetectorImpl::StartBluetoothHidDetection(
-    Delegate* delegate,
-    InputDevicesStatus input_devices_status) {
-  DCHECK(input_devices_status.pointer_is_missing ||
-         input_devices_status.keyboard_is_missing)
-      << " StartBluetoothHidDetection() called when neither pointer or "
-      << "keyboard is missing";
-  DCHECK_EQ(kNotStarted, state_);
-  HID_LOG(EVENT) << "Starting Bluetooth HID detection, pointer missing: "
-                 << input_devices_status.pointer_is_missing
-                 << ", keyboard missing: "
-                 << input_devices_status.keyboard_is_missing;
-  delegate_ = delegate;
-  input_devices_status_ = input_devices_status;
-  state_ = kStarting;
-  GetBluetoothConfigService(
-      cros_bluetooth_config_remote_.BindNewPipeAndPassReceiver());
-  cros_bluetooth_config_remote_->ObserveSystemProperties(
-      system_properties_observer_receiver_.BindNewPipeAndPassRemote());
-}
-
-void BluetoothHidDetectorImpl::StopBluetoothHidDetection() {
-  DCHECK_NE(kNotStarted, state_)
-      << " Call to StopBluetoothHidDetection() while "
-      << "HID detection is inactive.";
-  HID_LOG(EVENT) << "Stopping Bluetooth HID detection";
-  state_ = kNotStarted;
-  cros_bluetooth_config_remote_->SetBluetoothHidDetectionActive(false);
-  cros_bluetooth_config_remote_.reset();
-  system_properties_observer_receiver_.reset();
-  ResetDiscoveryState();
-  delegate_ = nullptr;
-}
-
 void BluetoothHidDetectorImpl::SetInputDevicesStatus(
     InputDevicesStatus input_devices_status) {
   HID_LOG(EVENT) << "Input devices status set, pointer missing: "
@@ -142,6 +108,37 @@
       std::move(pairing_state)};
 }
 
+void BluetoothHidDetectorImpl::PerformStartBluetoothHidDetection(
+    InputDevicesStatus input_devices_status) {
+  DCHECK(input_devices_status.pointer_is_missing ||
+         input_devices_status.keyboard_is_missing)
+      << " StartBluetoothHidDetection() called when neither pointer or "
+      << "keyboard is missing";
+  DCHECK_EQ(kNotStarted, state_);
+  HID_LOG(EVENT) << "Starting Bluetooth HID detection, pointer missing: "
+                 << input_devices_status.pointer_is_missing
+                 << ", keyboard missing: "
+                 << input_devices_status.keyboard_is_missing;
+  input_devices_status_ = input_devices_status;
+  state_ = kStarting;
+  GetBluetoothConfigService(
+      cros_bluetooth_config_remote_.BindNewPipeAndPassReceiver());
+  cros_bluetooth_config_remote_->ObserveSystemProperties(
+      system_properties_observer_receiver_.BindNewPipeAndPassRemote());
+}
+
+void BluetoothHidDetectorImpl::PerformStopBluetoothHidDetection() {
+  DCHECK_NE(kNotStarted, state_)
+      << " Call to StopBluetoothHidDetection() while "
+      << "HID detection is inactive.";
+  HID_LOG(EVENT) << "Stopping Bluetooth HID detection";
+  state_ = kNotStarted;
+  cros_bluetooth_config_remote_->SetBluetoothHidDetectionActive(false);
+  cros_bluetooth_config_remote_.reset();
+  system_properties_observer_receiver_.reset();
+  ResetDiscoveryState();
+}
+
 void BluetoothHidDetectorImpl::OnPropertiesUpdated(
     chromeos::bluetooth_config::mojom::BluetoothSystemPropertiesPtr
         properties) {
@@ -301,7 +298,7 @@
   HID_LOG(EVENT) << "HandleKeyEntered called with " << num_keys_entered
                  << " keys entered";
   current_pairing_state_->num_keys_entered = num_keys_entered;
-  delegate_->OnBluetoothHidStatusChanged();
+  NotifyBluetoothHidDetectionStatusChanged();
 }
 
 bool BluetoothHidDetectorImpl::IsHidTypeMissing(
@@ -360,7 +357,7 @@
       device_pairing_delegate_receiver_.BindNewPipeAndPassRemote(),
       base::BindOnce(&BluetoothHidDetectorImpl::OnPairDevice,
                      weak_ptr_factory_.GetWeakPtr()));
-  delegate_->OnBluetoothHidStatusChanged();
+  NotifyBluetoothHidDetectionStatusChanged();
 }
 
 void BluetoothHidDetectorImpl::OnPairDevice(
@@ -397,7 +394,7 @@
   current_pairing_state_.reset();
   device_pairing_delegate_receiver_.reset();
   key_entered_handler_receiver_.reset();
-  delegate_->OnBluetoothHidStatusChanged();
+  NotifyBluetoothHidDetectionStatusChanged();
   ProcessQueue();
 }
 
@@ -415,8 +412,8 @@
       chromeos::bluetooth_config::mojom::BluetoothDevicePropertiesPtr>>();
   queued_device_ids_.clear();
 
-  // Inform |delegate_| that no device is currently pairing.
-  delegate_->OnBluetoothHidStatusChanged();
+  // Inform the client that no device is currently pairing.
+  NotifyBluetoothHidDetectionStatusChanged();
 }
 
 void BluetoothHidDetectorImpl::RequirePairingCode(
@@ -430,7 +427,7 @@
   key_entered_handler_receiver_.Bind(std::move(handler));
   current_pairing_state_ =
       BluetoothHidPairingState{code, /*num_keys_entered=*/0u};
-  delegate_->OnBluetoothHidStatusChanged();
+  NotifyBluetoothHidDetectionStatusChanged();
 }
 
 }  // namespace hid_detection
diff --git a/ash/components/hid_detection/bluetooth_hid_detector_impl.h b/ash/components/hid_detection/bluetooth_hid_detector_impl.h
index 23dfbae..ef30ca1 100644
--- a/ash/components/hid_detection/bluetooth_hid_detector_impl.h
+++ b/ash/components/hid_detection/bluetooth_hid_detector_impl.h
@@ -28,10 +28,6 @@
   ~BluetoothHidDetectorImpl() override;
 
   // BluetoothHidDetector:
-  void StartBluetoothHidDetection(
-      Delegate* delegate,
-      InputDevicesStatus input_devices_status) override;
-  void StopBluetoothHidDetection() override;
   void SetInputDevicesStatus(InputDevicesStatus input_devices_status) override;
   const BluetoothHidDetectionStatus GetBluetoothHidDetectionStatus() override;
 
@@ -56,6 +52,11 @@
     kStoppedExternally,
   };
 
+  // BluetoothHidDetector:
+  void PerformStartBluetoothHidDetection(
+      InputDevicesStatus input_devices_status) override;
+  void PerformStopBluetoothHidDetection() override;
+
   // chromeos::bluetooth_config::mojom::SystemPropertiesObserver
   void OnPropertiesUpdated(
       chromeos::bluetooth_config::mojom::BluetoothSystemPropertiesPtr
@@ -106,7 +107,7 @@
   // Resets properties related to discovery, pairing handlers and queueing.
   void ResetDiscoveryState();
 
-  // Informs |delegate_| "DisplayPasskey" or "DisplayPinCode" pairing
+  // Informs the client "DisplayPasskey" or "DisplayPinCode" pairing
   // authorization is required.
   void RequirePairingCode(
       const std::string& code,
@@ -131,7 +132,6 @@
   // code that should be displayed to the user for them to enter into the HID.
   absl::optional<BluetoothHidPairingState> current_pairing_state_;
 
-  Delegate* delegate_ = nullptr;
   InputDevicesStatus input_devices_status_;
   State state_ = kNotStarted;
 
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 727e955..229da58 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -259,7 +259,7 @@
 
 // Controls whether the selfie camera feature is enabled for Capture Mode.
 const base::Feature kCaptureModeSelfieCamera{"CaptureModeSelfieCamera",
-                                             base::FEATURE_DISABLED_BY_DEFAULT};
+                                             base::FEATURE_ENABLED_BY_DEFAULT};
 
 // If enabled, allow eSIM installation bypass the non-cellular internet
 // connectivity check.
@@ -1004,6 +1004,11 @@
 const base::Feature kMicMuteNotifications{"MicMuteNotifications",
                                           base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Disables the deprecated Messages cross-device integration, to be used
+// along side the flag preinstall-by-default (kMessagesPreinstall).
+const base::Feature kDisableMessagesCrossDeviceIntegration{
+    "DisableMessagesCrossDeviceIntegration", base::FEATURE_ENABLED_BY_DEFAULT};
+
 // Controls whether to enable the requirement of a minimum chrome version on the
 // device through the policy DeviceMinimumVersion. If the requirement is
 // not met and the warning time in the policy has expired, the user is
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index 35255d7..c049c7ba7 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -396,6 +396,8 @@
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kMicMuteNotifications;
 COMPONENT_EXPORT(ASH_CONSTANTS)
+extern const base::Feature kDisableMessagesCrossDeviceIntegration;
+COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kMinimumChromeVersion;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kMojoDBusRelay;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kMultilingualTyping;
diff --git a/ash/projector/projector_metrics.cc b/ash/projector/projector_metrics.cc
index d39616e8..8e5eae1 100644
--- a/ash/projector/projector_metrics.cc
+++ b/ash/projector/projector_metrics.cc
@@ -31,6 +31,9 @@
 constexpr char kProjectorPendingScreencastBatchIOTaskDurationHistogramName[] =
     "Ash.Projector.PendingScreencastBatchIOTaskDuration";
 
+constexpr char kProjectorPendingScreencastChangeIntervalHistogramName[] =
+    "Ash.Projector.PendingScreencastChangeInterval";
+
 // Appends the proper suffix to |prefix| based on whether the user is in tablet
 // mode or not.
 std::string GetHistogramName(const std::string& prefix) {
@@ -88,4 +91,14 @@
       kProjectorPendingScreencastBatchIOTaskDurationHistogramName, duration);
 }
 
+ASH_EXPORT void RecordPendingScreencastChangeInterval(
+    const base::TimeDelta interval) {
+  // The interval doesn't include the change between last finished uploading to
+  // new start uploading. We don't normally expect the interval is longer than
+  // 10s. If this limit is exceeded, then the metric would fall into an overflow
+  // bucket.
+  base::UmaHistogramTimes(
+      kProjectorPendingScreencastChangeIntervalHistogramName, interval);
+}
+
 }  // namespace ash
diff --git a/ash/projector/projector_metrics.h b/ash/projector/projector_metrics.h
index 62f2e05..4280f37a 100644
--- a/ash/projector/projector_metrics.h
+++ b/ash/projector/projector_metrics.h
@@ -112,6 +112,9 @@
 // Records the IO task processing Time for screencast validation.
 void RecordPendingScreencastBatchIOTaskDuration(const base::TimeDelta duration);
 
+// Records the interval between the UI changes of pending screencasts.
+void RecordPendingScreencastChangeInterval(const base::TimeDelta interval);
+
 }  // namespace ash
 
 #endif  // ASH_PROJECTOR_PROJECTOR_METRICS_H_
diff --git a/ash/shelf/home_button.cc b/ash/shelf/home_button.cc
index 131784f..cee433e 100644
--- a/ash/shelf/home_button.cc
+++ b/ash/shelf/home_button.cc
@@ -259,6 +259,17 @@
 }
 
 void HomeButton::StartNudgeAnimation() {
+  // Ensure any in-progress nudge animations are completed before initializing
+  // a new nudge animation, and creating a rippler layer. Nudge animation
+  // callbacks may otherwise delete ripple layer mid new animation set up (and
+  // delete the newly created ripple layer just before the layer animation is
+  // set up by animation builder).
+  nudge_ripple_layer_.ReleaseLayer();
+  if (nudge_label_)
+    nudge_label_->layer()->GetAnimator()->AbortAllAnimations();
+  if (label_container_)
+    label_container_->layer()->GetAnimator()->AbortAllAnimations();
+
   // Create the nudge label first to check if there is enough space to show it.
   if (!nudge_label_)
     CreateNudgeLabel();
diff --git a/ash/shelf/launcher_nudge_controller_unittest.cc b/ash/shelf/launcher_nudge_controller_unittest.cc
index 179510e7..94fa106 100644
--- a/ash/shelf/launcher_nudge_controller_unittest.cc
+++ b/ash/shelf/launcher_nudge_controller_unittest.cc
@@ -297,9 +297,8 @@
   EXPECT_EQ(1, waiter_secondary.GetShownCount());
 }
 
-// TODO(crbug.com/1324384): Disabled due to flakiness.
 TEST_F(LauncherNudgeControllerTest,
-       DISABLED_WaitUntilHomeButtonStaysLongEnoughToShowNudge) {
+       WaitUntilHomeButtonStaysLongEnoughToShowNudge) {
   // Set the animation duration mode to non-zero for the launcher nudge
   // animation to actually run in the tests.
   ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index d5904d6..63f704e 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -43,7 +43,9 @@
 #include "ui/compositor/paint_recorder.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/dip_util.h"
 #include "ui/gfx/geometry/rounded_corners_f.h"
+#include "ui/gfx/scoped_canvas.h"
 #include "ui/gfx/skbitmap_operations.h"
 #include "ui/views/accessible_pane_view.h"
 #include "ui/views/focus/focus_search.h"
@@ -180,9 +182,15 @@
     if (login_shelf_view_ && login_shelf_view_->GetVisible())
       return;
 
-    views::HighlightBorder::PaintBorderToCanvas(
-        canvas, *owner_view_, gfx::Rect(layer()->size()),
-        gfx::RoundedCornersF(corner_radius_), highlight_border_type_, false);
+    if (corner_radius_ > 0) {
+      views::HighlightBorder::PaintBorderToCanvas(
+          canvas, *owner_view_, gfx::Rect(layer()->size()),
+          gfx::RoundedCornersF(corner_radius_), highlight_border_type_, false);
+    } else {
+      // If the shelf corners are not rounded, only paint the highlight border
+      // on the inner edge of the shelf to separate the shelf and the work area.
+      PaintEdgeToCanvas(canvas);
+    }
   }
 
   void OnDeviceScaleFactorChanged(float old_device_scale_factor,
@@ -190,6 +198,77 @@
     layer()->SchedulePaint(gfx::Rect(layer()->size()));
   }
 
+  void PaintEdgeToCanvas(gfx::Canvas* canvas) {
+    SkColor inner_color = views::HighlightBorder::GetHighlightColor(
+        *owner_view_, highlight_border_type_, /*use_light_colors=*/false);
+    SkColor outer_color = views::HighlightBorder::GetBorderColor(
+        *owner_view_, highlight_border_type_, /*use_light_colors=*/false);
+
+    const int border_thickness = views::kHighlightBorderThickness;
+    const float half_thickness = border_thickness / 2.0f;
+
+    cc::PaintFlags flags;
+    flags.setStrokeWidth(border_thickness);
+    flags.setColor(outer_color);
+    flags.setStyle(cc::PaintFlags::kStroke_Style);
+    flags.setAntiAlias(true);
+
+    // Scale bounds and corner radius with device scale factor to make sure
+    // border bounds match content bounds but keep border stroke width the same.
+    gfx::ScopedCanvas scoped_canvas(canvas);
+    const float dsf = canvas->UndoDeviceScaleFactor();
+    const gfx::RectF pixel_bounds =
+        gfx::ConvertRectToPixels(gfx::Rect(layer()->size()), dsf);
+
+    // The points that are used to draw the highlighted edge.
+    gfx::PointF start_point, end_point;
+
+    switch (shelf_->alignment()) {
+      case ShelfAlignment::kBottom:
+      case ShelfAlignment::kBottomLocked:
+        start_point = gfx::PointF(pixel_bounds.origin());
+        end_point = gfx::PointF(pixel_bounds.top_right());
+        start_point.Offset(0, half_thickness);
+        end_point.Offset(0, half_thickness);
+        break;
+      case ShelfAlignment::kLeft:
+        start_point = gfx::PointF(pixel_bounds.top_right());
+        end_point = gfx::PointF(pixel_bounds.bottom_right());
+        start_point.Offset(-half_thickness, 0);
+        end_point.Offset(-half_thickness, 0);
+        break;
+      case ShelfAlignment::kRight:
+        start_point = gfx::PointF(pixel_bounds.origin());
+        end_point = gfx::PointF(pixel_bounds.bottom_left());
+        start_point.Offset(half_thickness, 0);
+        end_point.Offset(half_thickness, 0);
+        break;
+    }
+
+    // Draw the outer line.
+    canvas->DrawLine(start_point, end_point, flags);
+
+    switch (shelf_->alignment()) {
+      case ShelfAlignment::kBottom:
+      case ShelfAlignment::kBottomLocked:
+        start_point.Offset(0, border_thickness);
+        end_point.Offset(0, border_thickness);
+        break;
+      case ShelfAlignment::kLeft:
+        start_point.Offset(-border_thickness, 0);
+        end_point.Offset(-border_thickness, 0);
+        break;
+      case ShelfAlignment::kRight:
+        start_point.Offset(border_thickness, 0);
+        end_point.Offset(border_thickness, 0);
+        break;
+    }
+
+    // Draw the inner line.
+    flags.setColor(inner_color);
+    canvas->DrawLine(start_point, end_point, flags);
+  }
+
   Shelf* const shelf_;
   views::View* const owner_view_;
   const bool draw_highlight_border_;
diff --git a/ash/system/message_center/unified_message_center_bubble_unittest.cc b/ash/system/message_center/unified_message_center_bubble_unittest.cc
index fbeea64..9b44183 100644
--- a/ash/system/message_center/unified_message_center_bubble_unittest.cc
+++ b/ash/system/message_center/unified_message_center_bubble_unittest.cc
@@ -333,45 +333,51 @@
 }
 
 TEST_P(UnifiedMessageCenterBubbleTest, BubbleBounds) {
-  // Set display size where the message center is not collapsed.
-  UpdateDisplay("0+0-1280x1024");
+  std::vector<std::string> displays = {"0+0-1200x800", "0+0-1280x1080",
+                                       "0+0-1600x1440"};
 
-  // Ensure message center is not collapsed.
-  GetPrimaryUnifiedSystemTray()->ShowBubble();
-  ASSERT_FALSE(GetMessageCenterBubble()->IsMessageCenterCollapsed());
+  for (auto display : displays) {
+    // Set display size where the message center is not collapsed.
+    UpdateDisplay(display);
 
-  // Add enough notifications so that the scroll bar is visible.
-  while (!GetMessageCenterBubble()->message_center_view()->IsScrollBarVisible())
-    AddNotification();
+    // Ensure message center is not collapsed.
+    GetPrimaryUnifiedSystemTray()->ShowBubble();
+    ASSERT_FALSE(GetMessageCenterBubble()->IsMessageCenterCollapsed());
 
-  // The message center bubble should be positioned above the system tray
-  // bubble.
-  GetPrimaryUnifiedSystemTray()->ShowBubble();
-  EXPECT_LT(GetMessageCenterBubble()->GetBoundsInScreen().bottom(),
-            GetSystemTrayBubble()->GetBoundsInScreen().y());
-  GetPrimaryUnifiedSystemTray()->CloseBubble();
+    // Add enough notifications so that the scroll bar is visible.
+    while (
+        !GetMessageCenterBubble()->message_center_view()->IsScrollBarVisible())
+      AddNotification();
 
-  // Go into overview mode, check bounds again.
-  EnterOverview();
-  GetPrimaryUnifiedSystemTray()->ShowBubble();
-  EXPECT_LT(GetMessageCenterBubble()->GetBoundsInScreen().bottom(),
-            GetSystemTrayBubble()->GetBoundsInScreen().y());
-  GetPrimaryUnifiedSystemTray()->CloseBubble();
-  ExitOverview();
+    // The message center bubble should be positioned above the system tray
+    // bubble.
+    GetPrimaryUnifiedSystemTray()->ShowBubble();
+    EXPECT_LT(GetMessageCenterBubble()->GetBoundsInScreen().bottom(),
+              GetSystemTrayBubble()->GetBoundsInScreen().y());
+    GetPrimaryUnifiedSystemTray()->CloseBubble();
 
-  // Go into tablet mode, check bounds again.
-  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
-  GetPrimaryUnifiedSystemTray()->ShowBubble();
-  EXPECT_LT(GetMessageCenterBubble()->GetBoundsInScreen().bottom(),
-            GetSystemTrayBubble()->GetBoundsInScreen().y());
-  GetPrimaryUnifiedSystemTray()->CloseBubble();
+    // Go into overview mode, check bounds again.
+    EnterOverview();
+    GetPrimaryUnifiedSystemTray()->ShowBubble();
+    EXPECT_LT(GetMessageCenterBubble()->GetBoundsInScreen().bottom(),
+              GetSystemTrayBubble()->GetBoundsInScreen().y());
+    GetPrimaryUnifiedSystemTray()->CloseBubble();
+    ExitOverview();
 
-  // Go into overview mode inside tablet mode, check bounds again.
-  EnterOverview();
-  GetPrimaryUnifiedSystemTray()->ShowBubble();
-  EXPECT_LT(GetMessageCenterBubble()->GetBoundsInScreen().bottom(),
-            GetSystemTrayBubble()->GetBoundsInScreen().y());
-  GetPrimaryUnifiedSystemTray()->CloseBubble();
+    // Go into tablet mode, check bounds again.
+    Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
+    GetPrimaryUnifiedSystemTray()->ShowBubble();
+    EXPECT_LT(GetMessageCenterBubble()->GetBoundsInScreen().bottom(),
+              GetSystemTrayBubble()->GetBoundsInScreen().y());
+    GetPrimaryUnifiedSystemTray()->CloseBubble();
+
+    // Go into overview mode inside tablet mode, check bounds again.
+    EnterOverview();
+    GetPrimaryUnifiedSystemTray()->ShowBubble();
+    EXPECT_LT(GetMessageCenterBubble()->GetBoundsInScreen().bottom(),
+              GetSystemTrayBubble()->GetBoundsInScreen().y());
+    GetPrimaryUnifiedSystemTray()->CloseBubble();
+  }
 }
 
 TEST_P(UnifiedMessageCenterBubbleTest, HandleAccelerators) {
diff --git a/ash/system/message_center/unified_message_center_view.cc b/ash/system/message_center/unified_message_center_view.cc
index 3bc230b..7fd23bd 100644
--- a/ash/system/message_center/unified_message_center_view.cc
+++ b/ash/system/message_center/unified_message_center_view.cc
@@ -140,9 +140,11 @@
 void UnifiedMessageCenterView::SetMaxHeight(int max_height) {
   int max_scroller_height = max_height;
   if (notification_bar_->GetVisible()) {
-    max_scroller_height -= is_notifications_refresh_enabled_
-                               ? notification_bar_->GetPreferredSize().height()
-                               : kStackedNotificationBarHeight;
+    max_scroller_height -=
+        is_notifications_refresh_enabled_
+            ? notification_bar_->GetPreferredSize().height() +
+                  2 * kMessageCenterPadding
+            : kStackedNotificationBarHeight;
   }
   scroller_->ClipHeightTo(0, max_scroller_height);
 }
diff --git a/ash/system/time/OWNERS b/ash/system/time/OWNERS
new file mode 100644
index 0000000..31520c6
--- /dev/null
+++ b/ash/system/time/OWNERS
@@ -0,0 +1 @@
+jiamingc@chromium.org
diff --git a/ash/system/time/calendar_view.cc b/ash/system/time/calendar_view.cc
index a1c6330..0cc9e51 100644
--- a/ash/system/time/calendar_view.cc
+++ b/ash/system/time/calendar_view.cc
@@ -1562,12 +1562,22 @@
     next_next_month_->DisableFocus();
     content_view_->SetFocusBehavior(FocusBehavior::ALWAYS);
   }
+
+  up_button_->SetTooltipText(l10n_util::GetStringUTF16(
+      IDS_ASH_CALENDAR_UP_BUTTON_EVENT_LIST_ACCESSIBLE_DESCRIPTION));
+  down_button_->SetTooltipText(l10n_util::GetStringUTF16(
+      IDS_ASH_CALENDAR_DOWN_BUTTON_EVENT_LIST_ACCESSIBLE_DESCRIPTION));
 }
 
 void CalendarView::OnCloseEventListAnimationComplete() {
   RemoveChildViewT(event_list_view_);
   event_list_view_ = nullptr;
   calendar_view_controller_->OnEventListClosed();
+
+  up_button_->SetTooltipText(l10n_util::GetStringUTF16(
+      IDS_ASH_CALENDAR_UP_BUTTON_ACCESSIBLE_DESCRIPTION));
+  down_button_->SetTooltipText(l10n_util::GetStringUTF16(
+      IDS_ASH_CALENDAR_DOWN_BUTTON_ACCESSIBLE_DESCRIPTION));
 }
 
 BEGIN_METADATA(CalendarView, views::View)
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index 4287de51..b800143 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -36,6 +36,7 @@
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/run_loop.h"
 #include "base/system/sys_info.h"
+#include "base/system/system_monitor.h"
 #include "chromeos/ash/components/dbus/rgbkbd/rgbkbd_client.h"
 #include "chromeos/dbus/audio/cras_audio_client.h"
 #include "chromeos/dbus/power/power_policy_controller.h"
@@ -91,7 +92,8 @@
 };
 
 AshTestHelper::AshTestHelper(ui::ContextFactory* context_factory)
-    : AuraTestHelper(context_factory) {
+    : AuraTestHelper(context_factory),
+      system_monitor_(std::make_unique<base::SystemMonitor>()) {
   views::ViewsTestHelperAura::SetFallbackTestViewsDelegateFactory(
       &MakeTestViewsDelegate);
 
diff --git a/ash/test/ash_test_helper.h b/ash/test/ash_test_helper.h
index 9579189..081cecd 100644
--- a/ash/test/ash_test_helper.h
+++ b/ash/test/ash_test_helper.h
@@ -25,19 +25,23 @@
 
 namespace aura {
 class Window;
-}
+}  // namespace aura
+
+namespace base {
+class SystemMonitor;
+}  // namespace base
 
 namespace display {
 class Display;
-}
+}  // namespace display
 
 namespace ui {
 class ContextFactory;
-}
+}  // namespace ui
 
 namespace views {
 class TestViewsDelegate;
-}
+}  // namespace views
 
 namespace ash {
 
@@ -49,7 +53,7 @@
 
 namespace input_method {
 class MockInputMethodManager;
-}
+}  // namespace input_method
 
 // A helper class that does common initialization required for Ash. Creates a
 // root window and an ash::Shell instance with a test delegate.
@@ -141,6 +145,10 @@
   class BluezDBusManagerInitializer;
   class PowerPolicyControllerInitializer;
 
+  // Must be constructed so that `base::SystemMonitor::Get()` returns a valid
+  // instance.
+  std::unique_ptr<base::SystemMonitor> system_monitor_;
+
   std::unique_ptr<base::test::ScopedCommandLine> command_line_ =
       std::make_unique<base::test::ScopedCommandLine>();
   std::unique_ptr<chromeos::system::ScopedFakeStatisticsProvider>
diff --git a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html
index 6c81191c..130e470 100644
--- a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html
+++ b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.html
@@ -1,4 +1,7 @@
 <style include="cr-shared-style shimless-rma-shared">
+  :host(:not([should-show-warning_])) .icon-message {
+    grid-template-columns: 1fr;
+  }
 </style>
 <base-page equal-panes>
   <div slot="left-pane">
diff --git a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.js b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.js
index c4f8c30f..d1db25504 100644
--- a/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.js
+++ b/ash/webui/shimless_rma/resources/reimaging_firmware_update_page.js
@@ -83,6 +83,7 @@
       shouldShowWarning_: {
         type: Boolean,
         value: false,
+        reflectToAttribute: true,
       },
     };
   }
diff --git a/ash/wm/desks/desks_bar_view.cc b/ash/wm/desks/desks_bar_view.cc
index 2c712d57..6a98996 100644
--- a/ash/wm/desks/desks_bar_view.cc
+++ b/ash/wm/desks/desks_bar_view.cc
@@ -30,7 +30,7 @@
 #include "ash/wm/desks/persistent_desks_bar_controller.h"
 #include "ash/wm/desks/scroll_arrow_button.h"
 #include "ash/wm/desks/templates/desks_templates_metrics_util.h"
-#include "ash/wm/desks/templates/desks_templates_presenter.h"
+#include "ash/wm/desks/templates/saved_desk_presenter.h"
 #include "ash/wm/desks/templates/saved_desk_util.h"
 #include "ash/wm/desks/zero_state_button.h"
 #include "ash/wm/overview/overview_controller.h"
@@ -219,7 +219,7 @@
       const bool should_show_templates_ui =
           saved_desk_util::IsSavedDesksEnabled() &&
           !bar_view_->overview_grid()->overview_session()->is_shutting_down() &&
-          DesksTemplatesPresenter::Get()->should_show_templates_ui();
+          SavedDeskPresenter::Get()->should_show_templates_ui();
       auto* zero_state_desks_templates_button =
           bar_view_->zero_state_desks_templates_button();
       const gfx::Size zero_state_desks_templates_button_size =
@@ -993,7 +993,7 @@
     return;
 
   const bool should_show_ui =
-      DesksTemplatesPresenter::Get()->should_show_templates_ui();
+      SavedDeskPresenter::Get()->should_show_templates_ui();
   const bool is_zero_state = IsZeroState();
 
   zero_state_desks_templates_button_->SetVisible(should_show_ui &&
diff --git a/ash/wm/desks/templates/desks_templates_test_util.cc b/ash/wm/desks/templates/desks_templates_test_util.cc
index d8cb015..7e633c9 100644
--- a/ash/wm/desks/templates/desks_templates_test_util.cc
+++ b/ash/wm/desks/templates/desks_templates_test_util.cc
@@ -8,10 +8,10 @@
 #include "ash/style/close_button.h"
 #include "ash/wm/desks/desks_bar_view.h"
 #include "ash/wm/desks/expanded_desks_bar_button.h"
-#include "ash/wm/desks/templates/desks_templates_presenter.h"
 #include "ash/wm/desks/templates/saved_desk_dialog_controller.h"
 #include "ash/wm/desks/templates/saved_desk_item_view.h"
 #include "ash/wm/desks/templates/saved_desk_library_view.h"
+#include "ash/wm/desks/templates/saved_desk_presenter.h"
 #include "ash/wm/desks/zero_state_button.h"
 #include "ash/wm/overview/overview_grid.h"
 #include "ash/wm/overview/overview_test_util.h"
@@ -69,15 +69,15 @@
 
 }  // namespace
 
-DesksTemplatesPresenterTestApi::DesksTemplatesPresenterTestApi(
-    DesksTemplatesPresenter* presenter)
+SavedDeskPresenterTestApi::SavedDeskPresenterTestApi(
+    SavedDeskPresenter* presenter)
     : presenter_(presenter) {
   DCHECK(presenter_);
 }
 
-DesksTemplatesPresenterTestApi::~DesksTemplatesPresenterTestApi() = default;
+SavedDeskPresenterTestApi::~SavedDeskPresenterTestApi() = default;
 
-void DesksTemplatesPresenterTestApi::SetOnUpdateUiClosure(
+void SavedDeskPresenterTestApi::SetOnUpdateUiClosure(
     base::OnceClosure closure) {
   DCHECK(!presenter_->on_update_ui_closure_for_testing_);
   presenter_->on_update_ui_closure_for_testing_ = std::move(closure);
@@ -213,7 +213,7 @@
   DCHECK(overview_session);
 
   base::RunLoop run_loop;
-  DesksTemplatesPresenterTestApi(overview_session->desks_templates_presenter())
+  SavedDeskPresenterTestApi(overview_session->saved_desk_presenter())
       .SetOnUpdateUiClosure(run_loop.QuitClosure());
   run_loop.Run();
 }
diff --git a/ash/wm/desks/templates/desks_templates_test_util.h b/ash/wm/desks/templates/desks_templates_test_util.h
index f51dc65e..05ddf42 100644
--- a/ash/wm/desks/templates/desks_templates_test_util.h
+++ b/ash/wm/desks/templates/desks_templates_test_util.h
@@ -26,26 +26,26 @@
 namespace ash {
 
 class CloseButton;
-class DesksTemplatesPresenter;
 class OverviewGrid;
 class PillButton;
 class RoundedImageView;
+class SavedDeskLibraryView;
+class SavedDeskPresenter;
 
-// Wrapper for `DesksTemplatesPresenter` that exposes internal state to test
+// Wrapper for `SavedDeskPresenter` that exposes internal state to test
 // functions.
-class DesksTemplatesPresenterTestApi {
+class SavedDeskPresenterTestApi {
  public:
-  explicit DesksTemplatesPresenterTestApi(DesksTemplatesPresenter* presenter);
-  DesksTemplatesPresenterTestApi(const DesksTemplatesPresenterTestApi&) =
+  explicit SavedDeskPresenterTestApi(SavedDeskPresenter* presenter);
+  SavedDeskPresenterTestApi(const SavedDeskPresenterTestApi&) = delete;
+  SavedDeskPresenterTestApi& operator=(const SavedDeskPresenterTestApi&) =
       delete;
-  DesksTemplatesPresenterTestApi& operator=(
-      const DesksTemplatesPresenterTestApi&) = delete;
-  ~DesksTemplatesPresenterTestApi();
+  ~SavedDeskPresenterTestApi();
 
   void SetOnUpdateUiClosure(base::OnceClosure closure);
 
  private:
-  DesksTemplatesPresenter* const presenter_;
+  SavedDeskPresenter* const presenter_;
 };
 
 // Wrapper for `SavedDeskLibraryView` that exposes internal state to test
diff --git a/ash/wm/desks/templates/desks_templates_unittest.cc b/ash/wm/desks/templates/desks_templates_unittest.cc
index 1ee7f2a..81fcb83e 100644
--- a/ash/wm/desks/templates/desks_templates_unittest.cc
+++ b/ash/wm/desks/templates/desks_templates_unittest.cc
@@ -25,7 +25,6 @@
 #include "ash/wm/desks/desks_test_util.h"
 #include "ash/wm/desks/expanded_desks_bar_button.h"
 #include "ash/wm/desks/templates/desks_templates_metrics_util.h"
-#include "ash/wm/desks/templates/desks_templates_presenter.h"
 #include "ash/wm/desks/templates/desks_templates_test_util.h"
 #include "ash/wm/desks/templates/save_desk_template_button.h"
 #include "ash/wm/desks/templates/save_desk_template_button_container.h"
@@ -36,6 +35,7 @@
 #include "ash/wm/desks/templates/saved_desk_item_view.h"
 #include "ash/wm/desks/templates/saved_desk_library_view.h"
 #include "ash/wm/desks/templates/saved_desk_name_view.h"
+#include "ash/wm/desks/templates/saved_desk_presenter.h"
 #include "ash/wm/desks/zero_state_button.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/overview/overview_constants.h"
@@ -953,10 +953,9 @@
   // Exit and reopen overview to delete the template.
   ToggleOverview();
   OpenOverviewAndShowTemplatesGrid();
-  const DesksTemplatesPresenter* desk_templates_presenter =
-      DesksTemplatesPresenter::Get();
-  EXPECT_EQ(desk_templates_presenter->GetMaxEntryCount(),
-            desk_templates_presenter->GetEntryCount());
+  const SavedDeskPresenter* saved_desk_presenter = SavedDeskPresenter::Get();
+  EXPECT_EQ(saved_desk_presenter->GetMaxEntryCount(),
+            saved_desk_presenter->GetEntryCount());
 
   // Verify that the button is re-enabled after we delete all templates and exit
   // the templates grid.
@@ -2921,7 +2920,7 @@
   WaitForDesksTemplatesUI();
 
   // Mocks saving templates with some browsers.
-  DesksTemplatesPresenter::Get()->SaveOrUpdateDeskTemplate(
+  SavedDeskPresenter::Get()->SaveOrUpdateDeskTemplate(
       /*is_update=*/false, Shell::GetPrimaryRootWindow(),
       std::move(desk_template));
 
@@ -3501,7 +3500,7 @@
             // `LocalDeskStorage` does not support
             // `EntriesAddedOrUpdatedRemotely`, so
             // manually call it to simluate what the real model would do.
-            DesksTemplatesPresenter::Get()->EntriesAddedOrUpdatedRemotely(
+            SavedDeskPresenter::Get()->EntriesAddedOrUpdatedRemotely(
                 {entry.get()});
             ASSERT_EQ(u"Desk 2", second_item->name_view()->GetText());
             ASSERT_EQ(u"Desk 2", second_item->desk_template()->template_name());
diff --git a/ash/wm/desks/templates/saved_desk_grid_view.cc b/ash/wm/desks/templates/saved_desk_grid_view.cc
index 9356fb7..6b4eaad 100644
--- a/ash/wm/desks/templates/saved_desk_grid_view.cc
+++ b/ash/wm/desks/templates/saved_desk_grid_view.cc
@@ -10,10 +10,10 @@
 #include "ash/public/cpp/desk_template.h"
 #include "ash/screen_util.h"
 #include "ash/shell.h"
-#include "ash/wm/desks/templates/desks_templates_presenter.h"
 #include "ash/wm/desks/templates/saved_desk_animations.h"
 #include "ash/wm/desks/templates/saved_desk_item_view.h"
 #include "ash/wm/desks/templates/saved_desk_name_view.h"
+#include "ash/wm/desks/templates/saved_desk_presenter.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/overview/overview_highlight_controller.h"
 #include "ash/wm/overview/overview_session.h"
diff --git a/ash/wm/desks/templates/saved_desk_item_view.cc b/ash/wm/desks/templates/saved_desk_item_view.cc
index 9bcea5d..cec9765 100644
--- a/ash/wm/desks/templates/saved_desk_item_view.cc
+++ b/ash/wm/desks/templates/saved_desk_item_view.cc
@@ -20,12 +20,12 @@
 #include "ash/wm/desks/desk.h"
 #include "ash/wm/desks/desks_textfield.h"
 #include "ash/wm/desks/templates/desks_templates_metrics_util.h"
-#include "ash/wm/desks/templates/desks_templates_presenter.h"
 #include "ash/wm/desks/templates/saved_desk_dialog_controller.h"
 #include "ash/wm/desks/templates/saved_desk_grid_view.h"
 #include "ash/wm/desks/templates/saved_desk_icon_container.h"
 #include "ash/wm/desks/templates/saved_desk_library_view.h"
 #include "ash/wm/desks/templates/saved_desk_name_view.h"
+#include "ash/wm/desks/templates/saved_desk_presenter.h"
 #include "ash/wm/overview/overview_constants.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/overview/overview_grid.h"
@@ -301,7 +301,7 @@
 void SavedDeskItemView::ReplaceTemplate(const std::string& uuid) {
   // Make sure we delete the template we are replacing first, so that we don't
   // get template name collisions.
-  DesksTemplatesPresenter::Get()->DeleteEntry(uuid);
+  SavedDeskPresenter::Get()->DeleteEntry(uuid);
   UpdateTemplateName();
   RecordReplaceTemplateHistogram();
 }
@@ -505,7 +505,7 @@
   desk_template_->set_template_name(name_view_->GetText());
   OnTemplateNameChanged(desk_template_->template_name());
 
-  DesksTemplatesPresenter::Get()->SaveOrUpdateDeskTemplate(
+  SavedDeskPresenter::Get()->SaveOrUpdateDeskTemplate(
       /*is_update=*/true, GetWidget()->GetNativeWindow()->GetRootWindow(),
       desk_template_->Clone());
 }
@@ -631,7 +631,7 @@
 }
 
 void SavedDeskItemView::OnDeleteTemplate() {
-  DesksTemplatesPresenter::Get()->DeleteEntry(
+  SavedDeskPresenter::Get()->DeleteEntry(
       desk_template_->uuid().AsLowercaseString());
 }
 
@@ -664,7 +664,7 @@
     delay = base::Seconds(3);
 #endif
 
-  DesksTemplatesPresenter::Get()->LaunchDeskTemplate(
+  SavedDeskPresenter::Get()->LaunchDeskTemplate(
       desk_template_->uuid().AsLowercaseString(), delay,
       GetWidget()->GetNativeWindow()->GetRootWindow());
 }
diff --git a/ash/wm/desks/templates/desks_templates_presenter.cc b/ash/wm/desks/templates/saved_desk_presenter.cc
similarity index 86%
rename from ash/wm/desks/templates/desks_templates_presenter.cc
rename to ash/wm/desks/templates/saved_desk_presenter.cc
index 72a2692..3c3ce15 100644
--- a/ash/wm/desks/templates/desks_templates_presenter.cc
+++ b/ash/wm/desks/templates/saved_desk_presenter.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/wm/desks/templates/desks_templates_presenter.h"
+#include "ash/wm/desks/templates/saved_desk_presenter.h"
 
 #include "ash/public/cpp/desk_template.h"
 #include "ash/public/cpp/desks_templates_delegate.h"
@@ -34,7 +34,7 @@
 
 namespace {
 
-DesksTemplatesPresenter* g_instance = nullptr;
+SavedDeskPresenter* g_instance = nullptr;
 
 // Toast names.
 constexpr char kMaximumDeskLaunchTemplateToastName[] =
@@ -51,8 +51,7 @@
 
 }  // namespace
 
-DesksTemplatesPresenter::DesksTemplatesPresenter(
-    OverviewSession* overview_session)
+SavedDeskPresenter::SavedDeskPresenter(OverviewSession* overview_session)
     : overview_session_(overview_session) {
   DCHECK(overview_session_);
 
@@ -64,42 +63,42 @@
   GetAllEntries(base::GUID(), Shell::GetPrimaryRootWindow());
 }
 
-DesksTemplatesPresenter::~DesksTemplatesPresenter() {
+SavedDeskPresenter::~SavedDeskPresenter() {
   DCHECK_EQ(g_instance, this);
   g_instance = nullptr;
 }
 
 // static
-DesksTemplatesPresenter* DesksTemplatesPresenter::Get() {
+SavedDeskPresenter* SavedDeskPresenter::Get() {
   DCHECK(g_instance);
   return g_instance;
 }
 
-size_t DesksTemplatesPresenter::GetEntryCount() const {
+size_t SavedDeskPresenter::GetEntryCount() const {
   return GetDeskModel()->GetEntryCount();
 }
 
-size_t DesksTemplatesPresenter::GetMaxEntryCount() const {
+size_t SavedDeskPresenter::GetMaxEntryCount() const {
   return GetDeskModel()->GetMaxEntryCount();
 }
 
-size_t DesksTemplatesPresenter::GetDeskTemplateEntryCount() const {
+size_t SavedDeskPresenter::GetDeskTemplateEntryCount() const {
   return GetDeskModel()->GetDeskTemplateEntryCount();
 }
 
-size_t DesksTemplatesPresenter::GetMaxDeskTemplateEntryCount() const {
+size_t SavedDeskPresenter::GetMaxDeskTemplateEntryCount() const {
   return GetDeskModel()->GetMaxDeskTemplateEntryCount();
 }
 
-size_t DesksTemplatesPresenter::GetSaveAndRecallDeskEntryCount() const {
+size_t SavedDeskPresenter::GetSaveAndRecallDeskEntryCount() const {
   return GetDeskModel()->GetSaveAndRecallDeskEntryCount();
 }
 
-size_t DesksTemplatesPresenter::GetMaxSaveAndRecallDeskEntryCount() const {
+size_t SavedDeskPresenter::GetMaxSaveAndRecallDeskEntryCount() const {
   return GetDeskModel()->GetMaxSaveAndRecallDeskEntryCount();
 }
 
-void DesksTemplatesPresenter::UpdateDesksTemplatesUI() {
+void SavedDeskPresenter::UpdateDesksTemplatesUI() {
   // The save as desk template button is hidden in tablet mode. The desks
   // templates button on the desk bar view and the desks templates grid are
   // hidden in tablet mode and if there no templates to view.
@@ -123,26 +122,25 @@
   }
 }
 
-void DesksTemplatesPresenter::GetAllEntries(const base::GUID& item_to_focus,
-                                            aura::Window* const root_window) {
+void SavedDeskPresenter::GetAllEntries(const base::GUID& item_to_focus,
+                                       aura::Window* const root_window) {
   weak_ptr_factory_.InvalidateWeakPtrs();
   GetDeskModel()->GetAllEntries(base::BindOnce(
-      &DesksTemplatesPresenter::OnGetAllEntries, weak_ptr_factory_.GetWeakPtr(),
+      &SavedDeskPresenter::OnGetAllEntries, weak_ptr_factory_.GetWeakPtr(),
       item_to_focus, root_window));
 }
 
-void DesksTemplatesPresenter::DeleteEntry(const std::string& template_uuid) {
+void SavedDeskPresenter::DeleteEntry(const std::string& template_uuid) {
   weak_ptr_factory_.InvalidateWeakPtrs();
   GetDeskModel()->DeleteEntry(
       template_uuid,
-      base::BindOnce(&DesksTemplatesPresenter::OnDeleteEntry,
+      base::BindOnce(&SavedDeskPresenter::OnDeleteEntry,
                      weak_ptr_factory_.GetWeakPtr(), template_uuid));
 }
 
-void DesksTemplatesPresenter::LaunchDeskTemplate(
-    const std::string& template_uuid,
-    base::TimeDelta delay,
-    aura::Window* root_window) {
+void SavedDeskPresenter::LaunchDeskTemplate(const std::string& template_uuid,
+                                            base::TimeDelta delay,
+                                            aura::Window* root_window) {
   // If we are at the max desk limit (currently is 8), a new desk
   // cannot be created, and a toast will be displayed to the user.
   if (!DesksController::Get()->CanCreateDesks()) {
@@ -161,22 +159,22 @@
 
   GetDeskModel()->GetEntryByUUID(
       template_uuid,
-      base::BindOnce(&DesksTemplatesPresenter::OnGetTemplateForDeskLaunch,
+      base::BindOnce(&SavedDeskPresenter::OnGetTemplateForDeskLaunch,
                      weak_ptr_factory_.GetWeakPtr(), base::Time::Now(), delay,
                      root_window));
 }
 
-void DesksTemplatesPresenter::MaybeSaveActiveDeskAsTemplate(
+void SavedDeskPresenter::MaybeSaveActiveDeskAsTemplate(
     DeskTemplateType template_type,
     aura::Window* root_window_to_show) {
   DesksController::Get()->CaptureActiveDeskAsTemplate(
-      base::BindOnce(&DesksTemplatesPresenter::SaveOrUpdateDeskTemplate,
+      base::BindOnce(&SavedDeskPresenter::SaveOrUpdateDeskTemplate,
                      weak_ptr_factory_.GetWeakPtr(),
                      /*is_update=*/false, root_window_to_show),
       template_type, root_window_to_show);
 }
 
-void DesksTemplatesPresenter::SaveOrUpdateDeskTemplate(
+void SavedDeskPresenter::SaveOrUpdateDeskTemplate(
     bool is_update,
     aura::Window* const root_window,
     std::unique_ptr<DeskTemplate> desk_template) {
@@ -198,26 +196,26 @@
   weak_ptr_factory_.InvalidateWeakPtrs();
   GetDeskModel()->AddOrUpdateEntry(
       std::move(desk_template),
-      base::BindOnce(&DesksTemplatesPresenter::OnAddOrUpdateEntry,
+      base::BindOnce(&SavedDeskPresenter::OnAddOrUpdateEntry,
                      weak_ptr_factory_.GetWeakPtr(), is_update, root_window,
                      std::move(desk_template_clone)));
 }
 
-void DesksTemplatesPresenter::OnDeskModelDestroying() {
+void SavedDeskPresenter::OnDeskModelDestroying() {
   desk_model_observation_.Reset();
 }
 
-void DesksTemplatesPresenter::EntriesAddedOrUpdatedRemotely(
+void SavedDeskPresenter::EntriesAddedOrUpdatedRemotely(
     const std::vector<const DeskTemplate*>& new_entries) {
   AddOrUpdateUIEntries(new_entries);
 }
 
-void DesksTemplatesPresenter::EntriesRemovedRemotely(
+void SavedDeskPresenter::EntriesRemovedRemotely(
     const std::vector<std::string>& uuids) {
   RemoveUIEntries(uuids);
 }
 
-void DesksTemplatesPresenter::OnGetAllEntries(
+void SavedDeskPresenter::OnGetAllEntries(
     const base::GUID& item_to_focus,
     aura::Window* const root_window,
     desks_storage::DeskModel::GetAllEntriesStatus status,
@@ -254,7 +252,7 @@
     std::move(on_update_ui_closure_for_testing_).Run();
 }
 
-void DesksTemplatesPresenter::OnDeleteEntry(
+void SavedDeskPresenter::OnDeleteEntry(
     const std::string& template_uuid,
     desks_storage::DeskModel::DeleteEntryStatus status) {
   if (status != desks_storage::DeskModel::DeleteEntryStatus::kOk)
@@ -265,7 +263,7 @@
   RemoveUIEntries({template_uuid});
 }
 
-void DesksTemplatesPresenter::OnGetTemplateForDeskLaunch(
+void SavedDeskPresenter::OnGetTemplateForDeskLaunch(
     base::Time time_launch_started,
     base::TimeDelta delay,
     aura::Window* root_window,
@@ -283,7 +281,7 @@
   const bool activate_desk = entry->type() == DeskTemplateType::kTemplate;
   DesksController::Get()->CreateNewDeskForTemplate(
       template_name, activate_desk,
-      base::BindOnce(&DesksTemplatesPresenter::OnNewDeskCreatedForTemplate,
+      base::BindOnce(&SavedDeskPresenter::OnNewDeskCreatedForTemplate,
                      weak_ptr_factory_.GetWeakPtr(), std::move(entry),
                      time_launch_started, delay, root_window));
 
@@ -293,7 +291,7 @@
   RecordLaunchTemplateHistogram();
 }
 
-void DesksTemplatesPresenter::OnNewDeskCreatedForTemplate(
+void SavedDeskPresenter::OnNewDeskCreatedForTemplate(
     std::unique_ptr<DeskTemplate> desk_template,
     base::Time time_launch_started,
     base::TimeDelta delay,
@@ -325,7 +323,7 @@
     DeleteEntry(template_uuid);
 }
 
-void DesksTemplatesPresenter::OnAddOrUpdateEntry(
+void SavedDeskPresenter::OnAddOrUpdateEntry(
     bool was_update,
     aura::Window* const root_window,
     std::unique_ptr<DeskTemplate> desk_template,
@@ -403,7 +401,7 @@
   // wait for the `GetAllEntries` fired in `ShowDesksTemplatesGrids`.
 }
 
-void DesksTemplatesPresenter::AddOrUpdateUIEntries(
+void SavedDeskPresenter::AddOrUpdateUIEntries(
     const std::vector<const DeskTemplate*>& new_entries) {
   if (new_entries.empty())
     return;
@@ -423,7 +421,7 @@
     std::move(on_update_ui_closure_for_testing_).Run();
 }
 
-void DesksTemplatesPresenter::RemoveUIEntries(
+void SavedDeskPresenter::RemoveUIEntries(
     const std::vector<std::string>& uuids) {
   if (uuids.empty())
     return;
diff --git a/ash/wm/desks/templates/desks_templates_presenter.h b/ash/wm/desks/templates/saved_desk_presenter.h
similarity index 87%
rename from ash/wm/desks/templates/desks_templates_presenter.h
rename to ash/wm/desks/templates/saved_desk_presenter.h
index 15fd0e2..5f40e494 100644
--- a/ash/wm/desks/templates/desks_templates_presenter.h
+++ b/ash/wm/desks/templates/saved_desk_presenter.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_WM_DESKS_TEMPLATES_DESKS_TEMPLATES_PRESENTER_H_
-#define ASH_WM_DESKS_TEMPLATES_DESKS_TEMPLATES_PRESENTER_H_
+#ifndef ASH_WM_DESKS_TEMPLATES_SAVED_DESK_PRESENTER_H_
+#define ASH_WM_DESKS_TEMPLATES_SAVED_DESK_PRESENTER_H_
 
 #include <vector>
 
@@ -22,24 +22,24 @@
 class OverviewSession;
 enum class DeskTemplateType;
 
-// DesksTemplatesPresenter is the presenter for the desks templates UI. It
-// handles all calls to the model, and lets the UI know what to show or update.
+// SavedDeskPresenter is the presenter for the saved desk UI. It handles all
+// calls to the model, and lets the UI know what to show or update.
 // OverviewSession will create and own an instance of this object. It will be
 // created after the desks bar is visible and destroyed once we receive an
 // overview shutdown signal, to prevent calls to the model during shutdown.
-class ASH_EXPORT DesksTemplatesPresenter : desks_storage::DeskModelObserver {
+class ASH_EXPORT SavedDeskPresenter : desks_storage::DeskModelObserver {
  public:
-  explicit DesksTemplatesPresenter(OverviewSession* overview_session);
-  DesksTemplatesPresenter(const DesksTemplatesPresenter&) = delete;
-  DesksTemplatesPresenter& operator=(const DesksTemplatesPresenter&) = delete;
-  ~DesksTemplatesPresenter() override;
+  explicit SavedDeskPresenter(OverviewSession* overview_session);
+  SavedDeskPresenter(const SavedDeskPresenter&) = delete;
+  SavedDeskPresenter& operator=(const SavedDeskPresenter&) = delete;
+  ~SavedDeskPresenter() override;
 
   // Convenience function to get the presenter instance, which is created and
   // owned by `OverviewSession`.
   // TODO(crbug.com/1322553): Remove this function as `Get()` is normally used
   // for singletons, or for objects whose lifetimes are deterministic and live
   // as long as ash lives.
-  static DesksTemplatesPresenter* Get();
+  static SavedDeskPresenter* Get();
 
   bool should_show_templates_ui() { return should_show_templates_ui_; }
 
@@ -97,7 +97,7 @@
   void EntriesRemovedLocally(const std::vector<std::string>& uuids) override {}
 
  private:
-  friend class DesksTemplatesPresenterTestApi;
+  friend class SavedDeskPresenterTestApi;
 
   // Callback ran after querying the model for a list of entries. This function
   // also contains logic for updating the UI.
@@ -154,9 +154,9 @@
   // the model.
   base::OnceClosure on_update_ui_closure_for_testing_;
 
-  base::WeakPtrFactory<DesksTemplatesPresenter> weak_ptr_factory_{this};
+  base::WeakPtrFactory<SavedDeskPresenter> weak_ptr_factory_{this};
 };
 
 }  // namespace ash
 
-#endif  // ASH_WM_DESKS_TEMPLATES_DESKS_TEMPLATES_PRESENTER_H_
+#endif  // ASH_WM_DESKS_TEMPLATES_SAVED_DESK_PRESENTER_H_
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index 6f1add0..90d5b9b 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -32,13 +32,13 @@
 #include "ash/wm/desks/desks_controller.h"
 #include "ash/wm/desks/desks_util.h"
 #include "ash/wm/desks/expanded_desks_bar_button.h"
-#include "ash/wm/desks/templates/desks_templates_presenter.h"
 #include "ash/wm/desks/templates/save_desk_template_button.h"
 #include "ash/wm/desks/templates/save_desk_template_button_container.h"
 #include "ash/wm/desks/templates/saved_desk_animations.h"
 #include "ash/wm/desks/templates/saved_desk_grid_view.h"
 #include "ash/wm/desks/templates/saved_desk_library_view.h"
 #include "ash/wm/desks/templates/saved_desk_name_view.h"
+#include "ash/wm/desks/templates/saved_desk_presenter.h"
 #include "ash/wm/desks/templates/saved_desk_util.h"
 #include "ash/wm/desks/zero_state_button.h"
 #include "ash/wm/mru_window_tracker.h"
@@ -1929,8 +1929,7 @@
   }
 
   // Enable/disable button and update tooltip.
-  const DesksTemplatesPresenter* desk_templates_presenter =
-      DesksTemplatesPresenter::Get();
+  const SavedDeskPresenter* saved_desk_presenter = SavedDeskPresenter::Get();
   SaveDeskTemplateButtonContainer* container =
       static_cast<SaveDeskTemplateButtonContainer*>(
           save_desk_button_container_widget_->GetContentsView());
@@ -1938,13 +1937,13 @@
   // `DeskTemplateType`, update `kSaveForLaterButton` to use its own count.
   container->UpdateButtonEnableStateAndTooltip(
       SaveDeskTemplateButton::Type::kSaveAsTemplate,
-      desk_templates_presenter->GetEntryCount(),
-      desk_templates_presenter->GetMaxEntryCount(), num_incognito_windows_,
+      saved_desk_presenter->GetEntryCount(),
+      saved_desk_presenter->GetMaxEntryCount(), num_incognito_windows_,
       num_unsupported_windows_, size());
   container->UpdateButtonEnableStateAndTooltip(
       SaveDeskTemplateButton::Type::kSaveForLater,
-      desk_templates_presenter->GetEntryCount(),
-      desk_templates_presenter->GetMaxEntryCount(), num_incognito_windows_,
+      saved_desk_presenter->GetEntryCount(),
+      saved_desk_presenter->GetMaxEntryCount(), num_incognito_windows_,
       num_unsupported_windows_, size());
 
   // Set the widget position above the overview item window and default width
@@ -2472,13 +2471,13 @@
 }
 
 void OverviewGrid::OnSaveDeskAsTemplateButtonPressed() {
-  DesksTemplatesPresenter::Get()->MaybeSaveActiveDeskAsTemplate(
+  SavedDeskPresenter::Get()->MaybeSaveActiveDeskAsTemplate(
       DeskTemplateType::kTemplate,
       save_desk_button_container_widget_->GetNativeWindow()->GetRootWindow());
 }
 
 void OverviewGrid::OnSaveDeskForLaterButtonPressed() {
-  DesksTemplatesPresenter::Get()->MaybeSaveActiveDeskAsTemplate(
+  SavedDeskPresenter::Get()->MaybeSaveActiveDeskAsTemplate(
       DeskTemplateType::kSaveAndRecall,
       save_desk_button_container_widget_->GetNativeWindow()->GetRootWindow());
 }
diff --git a/ash/wm/overview/overview_session.cc b/ash/wm/overview/overview_session.cc
index 8582906..42a130b 100644
--- a/ash/wm/overview/overview_session.cc
+++ b/ash/wm/overview/overview_session.cc
@@ -31,9 +31,9 @@
 #include "ash/wm/desks/desks_bar_view.h"
 #include "ash/wm/desks/desks_controller.h"
 #include "ash/wm/desks/desks_util.h"
-#include "ash/wm/desks/templates/desks_templates_presenter.h"
 #include "ash/wm/desks/templates/saved_desk_dialog_controller.h"
 #include "ash/wm/desks/templates/saved_desk_library_view.h"
+#include "ash/wm/desks/templates/saved_desk_presenter.h"
 #include "ash/wm/desks/templates/saved_desk_util.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/overview/overview_controller.h"
@@ -184,9 +184,8 @@
   }
 
   // Create this before the desks bar widget.
-  if (saved_desk_util::IsSavedDesksEnabled() && !desks_templates_presenter_) {
-    desks_templates_presenter_ =
-        std::make_unique<DesksTemplatesPresenter>(this);
+  if (saved_desk_util::IsSavedDesksEnabled() && !saved_desk_presenter_) {
+    saved_desk_presenter_ = std::make_unique<SavedDeskPresenter>(this);
     saved_desk_dialog_controller_ =
         std::make_unique<SavedDeskDialogController>();
   }
@@ -298,7 +297,7 @@
 
   // Stop the presenter from receiving any events that may update the model or
   // UI.
-  desks_templates_presenter_.reset();
+  saved_desk_presenter_.reset();
 
   // Resetting here will close any dialogs, and DCHECK anyone trying to open a
   // dialog past this point.
@@ -1036,7 +1035,7 @@
   // Only ask for all entries if it is the first time creating the grid widgets.
   // Otherwise, add or update the entries one at a time.
   if (created_grid_widgets)
-    desks_templates_presenter_->GetAllEntries(item_to_focus, root_window);
+    saved_desk_presenter_->GetAllEntries(item_to_focus, root_window);
   UpdateNoWindowsWidgetOnEachGrid();
 
   UpdateAccessibilityFocus();
@@ -1301,7 +1300,7 @@
         return;
 
       // There are no templates to be viewed.
-      if (!DesksTemplatesPresenter::Get()->should_show_templates_ui())
+      if (!saved_desk_presenter_->should_show_templates_ui())
         return;
 
       DCHECK(!grid_list_.empty());
@@ -1422,8 +1421,8 @@
 
 void OverviewSession::OnTabletModeChanged() {
   DCHECK(saved_desk_util::IsSavedDesksEnabled());
-  DCHECK(desks_templates_presenter_);
-  desks_templates_presenter_->UpdateDesksTemplatesUI();
+  DCHECK(saved_desk_presenter_);
+  saved_desk_presenter_->UpdateDesksTemplatesUI();
 }
 
 void OverviewSession::Move(bool reverse) {
diff --git a/ash/wm/overview/overview_session.h b/ash/wm/overview/overview_session.h
index 07e5720..dedaa8a 100644
--- a/ash/wm/overview/overview_session.h
+++ b/ash/wm/overview/overview_session.h
@@ -44,13 +44,13 @@
 
 namespace ash {
 
-class DesksTemplatesPresenter;
-class SavedDeskDialogController;
 class OverviewDelegate;
 class OverviewGrid;
 class OverviewHighlightController;
 class OverviewItem;
 class OverviewWindowDragController;
+class SavedDeskDialogController;
+class SavedDeskPresenter;
 
 // The Overview shows a grid of all of your windows, allowing to select
 // one by clicking or tapping on it.
@@ -373,8 +373,8 @@
     return highlight_controller_.get();
   }
 
-  DesksTemplatesPresenter* desks_templates_presenter() {
-    return desks_templates_presenter_.get();
+  SavedDeskPresenter* saved_desk_presenter() {
+    return saved_desk_presenter_.get();
   }
 
   void set_auto_add_windows_enabled(bool enabled) {
@@ -474,7 +474,7 @@
   std::unique_ptr<OverviewHighlightController> highlight_controller_;
 
   // The object responsible to talking to the desk model.
-  std::unique_ptr<DesksTemplatesPresenter> desks_templates_presenter_;
+  std::unique_ptr<SavedDeskPresenter> saved_desk_presenter_;
 
   std::unique_ptr<SavedDeskDialogController> saved_desk_dialog_controller_;
 
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index 83daa3d..66e5d24 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -503,24 +503,41 @@
   dex_dumps = dexdump.Dump(test_apk)
   tests = []
 
-  def get_test_methods(methods):
-    return [
-        {
-          'method': m,
-          # No annotation info is available from dexdump.
-          # Set MediumTest annotation for default.
-          'annotations': {'MediumTest': None},
-        } for m in methods if m.startswith('test')]
+  def get_test_methods(methods, annotations):
+    test_methods = []
+
+    for method in methods:
+      if method.startswith('test'):
+        method_annotations = annotations.get(method, {})
+
+        # Dexdump used to not return any annotation info
+        # So MediumTest annotation was added to all methods
+        # Preserving this behaviour by adding MediumTest if none of the
+        # size annotations are included in these annotations
+        if not any(valid in method_annotations for valid in _VALID_ANNOTATIONS):
+          method_annotations.update({'MediumTest': None})
+
+        test_methods.append({
+            'method': method,
+            'annotations': method_annotations
+        })
+
+    return test_methods
 
   for dump in dex_dumps:
     for package_name, package_info in six.iteritems(dump):
       for class_name, class_info in six.iteritems(package_info['classes']):
         if class_name.endswith('Test') and not class_info['is_abstract']:
+          classAnnotations, methodsAnnotations = class_info['annotations']
           tests.append({
-              'class': '%s.%s' % (package_name, class_name),
-              'annotations': {},
-              'methods': get_test_methods(class_info['methods']),
-              'superclass': class_info['superclass'],
+              'class':
+              '%s.%s' % (package_name, class_name),
+              'annotations':
+              classAnnotations,
+              'methods':
+              get_test_methods(class_info['methods'], methodsAnnotations),
+              'superclass':
+              class_info['superclass'],
           })
   return tests
 
@@ -620,6 +637,7 @@
     self._package_info = None
     self._suite = None
     self._test_apk = None
+    self._test_apk_as_instant = False
     self._test_apk_incremental_install_json = None
     self._test_jar = None
     self._test_package = None
@@ -714,6 +732,8 @@
     self._test_apk = apk_helper.ToHelper(test_apk_path)
     self._suite = os.path.splitext(os.path.basename(args.test_apk))[0]
 
+    self._test_apk_as_instant = args.test_apk_as_instant
+
     self._apk_under_test_incremental_install_json = (
         args.apk_under_test_incremental_install_json)
     self._test_apk_incremental_install_json = (
@@ -991,6 +1011,10 @@
     return self._test_apk
 
   @property
+  def test_apk_as_instant(self):
+    return self._test_apk_as_instant
+
+  @property
   def test_apk_incremental_install_json(self):
     return self._test_apk_incremental_install_json
 
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index 70fb033af..cc9b489 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -227,7 +227,8 @@
                          modules=None,
                          fake_modules=None,
                          permissions=None,
-                         additional_locales=None):
+                         additional_locales=None,
+                         instant_app=False):
 
         @instrumentation_tracing.no_tracing
         @trace_event.traced
@@ -237,7 +238,8 @@
                     modules=modules,
                     fake_modules=fake_modules,
                     permissions=permissions,
-                    additional_locales=additional_locales)
+                    additional_locales=additional_locales,
+                    instant_app=instant_app)
 
         return install_helper_internal
 
@@ -247,19 +249,25 @@
         def incremental_install_helper_internal(d, apk_path=None):
           # pylint: disable=unused-argument
           installer.Install(d, json_path, apk=apk, permissions=permissions)
+
         return incremental_install_helper_internal
 
       permissions = self._test_instance.test_apk.GetPermissions()
       if self._test_instance.test_apk_incremental_install_json:
-        steps.append(incremental_install_helper(
-                         self._test_instance.test_apk,
-                         self._test_instance.
-                             test_apk_incremental_install_json,
-                         permissions))
+        if self._test_instance.test_apk_as_instant:
+          raise Exception('Test APK cannot be installed as an instant '
+                          'app if it is incremental')
+
+        steps.append(
+            incremental_install_helper(
+                self._test_instance.test_apk,
+                self._test_instance.test_apk_incremental_install_json,
+                permissions))
       else:
         steps.append(
-            install_helper(
-                self._test_instance.test_apk, permissions=permissions))
+            install_helper(self._test_instance.test_apk,
+                           permissions=permissions,
+                           instant_app=self._test_instance.test_apk_as_instant))
 
       steps.extend(
           install_helper(apk) for apk in self._test_instance.additional_apks)
diff --git a/build/android/pylib/utils/dexdump.py b/build/android/pylib/utils/dexdump.py
index fb4142a..56f2494e 100644
--- a/build/android/pylib/utils/dexdump.py
+++ b/build/android/pylib/utils/dexdump.py
@@ -8,6 +8,8 @@
 import sys
 import tempfile
 from xml.etree import ElementTree
+from collections import namedtuple
+from typing import Dict
 
 from devil.utils import cmd_helper
 from pylib import constants
@@ -17,6 +19,9 @@
 
 DEXDUMP_PATH = os.path.join(constants.ANDROID_SDK_TOOLS, 'dexdump')
 
+Annotations = namedtuple('Annotations',
+                         ['classAnnotations', 'methodsAnnotations'])
+
 
 def Dump(apk_path):
   """Dumps class and method information from a APK into a dict via dexdump.
@@ -31,7 +36,8 @@
             <class_name>: {
               'methods': [<method_1>, <method_2>],
               'superclass': <string>,
-              'is_abstract': <boolean>
+              'is_abstract': <boolean>,
+              'annotations': <Annotations>
             }
           }
         }
@@ -44,7 +50,7 @@
                                            dexfile_dir,
                                            pattern='*classes*.dex'):
       output_xml = cmd_helper.GetCmdOutput(
-          [DEXDUMP_PATH, '-j', '-l', 'xml', dex_file])
+          [DEXDUMP_PATH, '-a', '-j', '-l', 'xml', dex_file])
       # Dexdump doesn't escape its XML output very well; decode it as utf-8 with
       # invalid sequences replaced, then remove forbidden characters and
       # re-encode it (as etree expects a byte string as input so it can figure
@@ -52,20 +58,123 @@
       BAD_XML_CHARS = re.compile(
           u'[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f-\x84\x86-\x9f' +
           u'\ud800-\udfff\ufdd0-\ufddf\ufffe-\uffff]')
-      if sys.version_info[0] < 3:
-        decoded_xml = output_xml.decode('utf-8', 'replace')
-        clean_xml = BAD_XML_CHARS.sub(u'\ufffd', decoded_xml)
-      else:
-        # Line duplicated to avoid pylint redefined-variable-type error.
-        clean_xml = BAD_XML_CHARS.sub(u'\ufffd', output_xml)
+
+      # Line duplicated to avoid pylint redefined-variable-type error.
+      clean_xml = BAD_XML_CHARS.sub(u'\ufffd', output_xml)
+
+      # Constructors are referenced as "<init>" in our annotations
+      # which will result in in the ElementTree failing to parse
+      # our xml as it won't find a closing tag for this
+      clean_xml = clean_xml.replace('<init>', 'constructor')
+
+      annotations = _ParseAnnotations(clean_xml)
+
       parsed_dex_files.append(
-          _ParseRootNode(ElementTree.fromstring(clean_xml.encode('utf-8'))))
+          _ParseRootNode(ElementTree.fromstring(clean_xml.encode('utf-8')),
+                         annotations))
     return parsed_dex_files
   finally:
     shutil.rmtree(dexfile_dir)
 
 
-def _ParseRootNode(root):
+def _ParseAnnotations(dexRaw: str) -> Dict[int, Annotations]:
+  """ Parse XML strings and return a list of Annotations mapped to
+  classes by index.
+
+  Annotations are written to the dex dump as human readable blocks of text
+  The only prescription is that they appear before the class in our xml file
+  They are not required to be nested within the package as our classes
+  It is simpler to parse for all the annotations and then associate them
+  back to the
+  classes
+
+  Example:
+  Class #12 annotations:
+  Annotations on class
+    VISIBILITY_RUNTIME Ldalvik/annotation/EnclosingClass; value=...
+  Annotations on method #512 'example'
+    VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value=...
+  """
+
+  # We want to find the lines matching the annotations header pattern
+  # Eg: Class #12 annotations -> true
+  annotationsBlockMatcher = re.compile(u'^Class #.*annotations:$')
+  # We want to retrieve the index of the class
+  # Eg: Class #12 annotations -> 12
+  classIndexMatcher = re.compile(u'(?<=#)[0-9]*')
+  # We want to retrieve the method name from between the quotes
+  # of the annotations line
+  # Eg: Annotations on method #512 'example'  -> example
+  methodMatcher = re.compile(u"(?<=')[^']*")
+  # We want to match everything after the last slash until before the semi colon
+  # Eg: Ldalvik/annotation/Signature; -> Signature
+  annotationMatcher = re.compile(u'[^/]*(?=;)')
+
+  annotations = {}
+  currentAnnotationsForClass = None
+  currentAnnotationsBlock: Dict[str, None] = None
+
+  # This loop does four things
+  # 1. It looks for a line telling us we are describing annotations for
+  #  a new class
+  # 2. It looks for a line telling us if the annotations we find will be
+  #  for the class or for any of it's methods; we will keep reference to
+  #  this
+  # 3. It adds the annotations to whatever we are holding reference to
+  # 4. It looks for a line to see if we should start looking for a
+  #  new class again
+  for line in dexRaw.splitlines():
+    if currentAnnotationsForClass is None:
+      # Step 1
+      # We keep searching until we find an annotation descriptor
+      # This lets us know that we are storing annotations for a new class
+      if annotationsBlockMatcher.match(line):
+        currentClassIndex = int(classIndexMatcher.findall(line)[0])
+        currentAnnotationsForClass = Annotations(classAnnotations={},
+                                                 methodsAnnotations={})
+        annotations[currentClassIndex] = currentAnnotationsForClass
+    else:
+      # Step 2
+      # If we find a descriptor indicating we are tracking annotations
+      # for the class or it's methods, we'll keep a reference of this
+      # block for when we start finding annotation references
+      if line.startswith(u'Annotations on class'):
+        currentAnnotationsBlock = currentAnnotationsForClass.classAnnotations
+      elif line.startswith(u'Annotations on method'):
+        method = methodMatcher.findall(line)[0]
+        currentAnnotationsBlock = {}
+        currentAnnotationsForClass.methodsAnnotations[
+            method] = currentAnnotationsBlock
+
+      # If we match against any other type of annotations
+      # we will ignore them
+      elif line.startswith(u'Annotations on'):
+        currentAnnotationsBlock = None
+
+      # Step 3
+      # We are only adding runtime annotations as those are the types
+      # that will affect if we should run tests or not (where this is
+      # being used)
+      elif currentAnnotationsBlock is not None and line.strip().startswith(
+          'VISIBILITY_RUNTIME'):
+        annotation = annotationMatcher.findall(line)[0]
+
+        # Our instrumentation tests expect a mapping of "Annotation: Value"
+        # We aren't using the value for anything and this would increase
+        # the complexity of this parser so just mapping these to None
+        currentAnnotationsBlock.update({annotation: None})
+
+      # Step 4
+      # Empty lines indicate that the annotation descriptions are complete
+      # and we should look for new classes
+      elif not line.strip():
+        currentAnnotationsForClass = None
+        currentAnnotationsBlock = None
+
+  return annotations
+
+
+def _ParseRootNode(root, annotations: Dict[int, Annotations]):
   """Parses the XML output of dexdump. This output is in the following format.
 
   This is a subset of the information contained within dexdump output.
@@ -88,10 +197,17 @@
   </api>
   """
   results = {}
+
+  # Annotations are referenced by the class order
+  # To match them, we need to keep track of the class number and
+  # match it to the appropriate annotation at that stage
+  classCount = 0
+
   for child in root:
     if child.tag == 'package':
       package_name = child.attrib['name']
-      parsed_node = _ParsePackageNode(child)
+      parsed_node, classCount = _ParsePackageNode(child, classCount,
+                                                  annotations)
       if package_name in results:
         results[package_name]['classes'].update(parsed_node['classes'])
       else:
@@ -99,34 +215,40 @@
   return results
 
 
-def _ParsePackageNode(package_node):
+def _ParsePackageNode(package_node, classCount: int,
+                      annotations: Dict[int, Annotations]):
   """Parses a <package> node from the dexdump xml output.
 
   Returns:
-    A dict in the format:
-      {
+    A tuple in the format:
+      (classes: {
         'classes': {
           <class_1>: {
             'methods': [<method_1>, <method_2>],
             'superclass': <string>,
-            'is_abstract': <boolean>
+            'is_abstract': <boolean>,
+            'annotations': <Annotations or None>
           },
           <class_2>: {
             'methods': [<method_1>, <method_2>],
             'superclass': <string>,
-            'is_abstract': <boolean>
+            'is_abstract': <boolean>,
+            'annotations': <Annotations or None>
           },
         }
-      }
+      }, classCount: number)
   """
   classes = {}
   for child in package_node:
     if child.tag == 'class':
-      classes[child.attrib['name']] = _ParseClassNode(child)
-  return {'classes': classes}
+      classes[child.attrib['name']] = _ParseClassNode(child, classCount,
+                                                      annotations)
+      classCount += 1
+  return ({'classes': classes}, classCount)
 
 
-def _ParseClassNode(class_node):
+def _ParseClassNode(class_node, classIndex: int,
+                    annotations: Dict[int, Annotations]):
   """Parses a <class> node from the dexdump xml output.
 
   Returns:
@@ -142,7 +264,13 @@
     if child.tag == 'method' and child.attrib['visibility'] == 'public':
       methods.append(child.attrib['name'])
   return {
-      'methods': methods,
-      'superclass': class_node.attrib['extends'],
-      'is_abstract': class_node.attrib.get('abstract') == 'true'
+      'methods':
+      methods,
+      'superclass':
+      class_node.attrib['extends'],
+      'is_abstract':
+      class_node.attrib.get('abstract') == 'true',
+      'annotations':
+      annotations.get(classIndex,
+                      Annotations(classAnnotations={}, methodsAnnotations={}))
   }
diff --git a/build/android/pylib/utils/dexdump_test.py b/build/android/pylib/utils/dexdump_test.py
index fb04164d..27f2a10a 100755
--- a/build/android/pylib/utils/dexdump_test.py
+++ b/build/android/pylib/utils/dexdump_test.py
@@ -10,9 +10,41 @@
 
 # pylint: disable=protected-access
 
+emptyAnnotations = dexdump.Annotations(classAnnotations={},
+                                       methodsAnnotations={})
+
 
 class DexdumpXMLParseTest(unittest.TestCase):
 
+  def testParseAnnotations(self):
+    example_xml_string = (
+        '<package name="com.foo.bar">\n'
+        'Class #1 annotations:\n'
+        'Annotations on class\n'
+        ' VISIBILITY_RUNTIME Ldalvik/annotation/AppModeFull; value=...\n'
+        'Annotations on method #512 \'example\'\n'
+        ' VISIBILITY_SYSTEM Ldalvik/annotation/Signature; value=...\n'
+        ' VISIBILITY_RUNTIME Ldalvik/annotation/Test; value=...\n'
+        '<class name="Class1" extends="java.lang.Object">\n'
+        '</class>\n'
+        '<class name="Class2" extends="java.lang.Object">\n'
+        '</class>\n'
+        '</package>\n')
+
+    actual = dexdump._ParseAnnotations(example_xml_string)
+
+    expected = {
+        1:
+        dexdump.Annotations(
+            classAnnotations={'AppModeFull': None},
+            methodsAnnotations={'example': {
+                'Test': None
+            }},
+        )
+    }
+
+    self.assertEqual(expected, actual)
+
   def testParseRootXmlNode(self):
     example_xml_string = ('<api>'
                           '<package name="com.foo.bar1">'
@@ -69,8 +101,8 @@
                           '</package>'
                           '</api>')
 
-    actual = dexdump._ParseRootNode(
-        ElementTree.fromstring(example_xml_string))
+    actual = dexdump._ParseRootNode(ElementTree.fromstring(example_xml_string),
+                                    {})
 
     expected = {
         'com.foo.bar1': {
@@ -79,11 +111,13 @@
                     'methods': ['class1Method1', 'class1Method2'],
                     'superclass': 'java.lang.Object',
                     'is_abstract': False,
+                    'annotations': emptyAnnotations,
                 },
                 'Class2': {
                     'methods': ['class2Method1'],
                     'superclass': 'java.lang.Object',
                     'is_abstract': True,
+                    'annotations': emptyAnnotations,
                 }
             },
         },
@@ -106,8 +140,8 @@
         '</package>')
 
 
-    actual = dexdump._ParsePackageNode(
-        ElementTree.fromstring(example_xml_string))
+    (actual, classCount) = dexdump._ParsePackageNode(
+        ElementTree.fromstring(example_xml_string), 0, {})
 
     expected = {
         'classes': {
@@ -115,15 +149,18 @@
                 'methods': [],
                 'superclass': 'java.lang.Object',
                 'is_abstract': False,
+                'annotations': emptyAnnotations,
             },
             'Class2': {
                 'methods': [],
                 'superclass': 'java.lang.Object',
                 'is_abstract': True,
+                'annotations': emptyAnnotations,
             },
         },
     }
     self.assertEqual(expected, actual)
+    self.assertEqual(classCount, 2)
 
   def testParseClassNode(self):
     example_xml_string = ('<class name="Class1" extends="java.lang.Object">'
@@ -135,13 +172,14 @@
                           '</method>'
                           '</class>')
 
-    actual = dexdump._ParseClassNode(
-        ElementTree.fromstring(example_xml_string))
+    actual = dexdump._ParseClassNode(ElementTree.fromstring(example_xml_string),
+                                     0, {})
 
     expected = {
         'methods': ['method1', 'method2'],
         'superclass': 'java.lang.Object',
         'is_abstract': False,
+        'annotations': emptyAnnotations,
     }
     self.assertEqual(expected, actual)
 
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 9c1b3858..3a61380 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -540,6 +540,11 @@
       required=True,
       help='Path or name of the apk containing the tests.')
   parser.add_argument(
+      '--test-apk-as-instant',
+      action='store_true',
+      help='Install the test apk as an instant app. '
+      'Instant apps run in a more restrictive execution environment.')
+  parser.add_argument(
       '--test-jar',
       help='Path of jar containing test java files.')
   parser.add_argument(
diff --git a/build/config/fuchsia/sizes.gni b/build/config/fuchsia/sizes.gni
index 20a5bf8..c081c26 100644
--- a/build/config/fuchsia/sizes.gni
+++ b/build/config/fuchsia/sizes.gni
@@ -30,7 +30,7 @@
     # swarming test client.
     data += [
       "//build/fuchsia/",
-      "//fuchsia/release/size_tests/",
+      "//tools/fuchsia/size_tests/",
       "//third_party/fuchsia-sdk/sdk/arch/",
       "//third_party/fuchsia-sdk/sdk/tools/${target_cpu}/",
     ]
diff --git a/build/fuchsia/OWNERS b/build/fuchsia/OWNERS
index d023b30..1187c74e 100644
--- a/build/fuchsia/OWNERS
+++ b/build/fuchsia/OWNERS
@@ -8,3 +8,6 @@
 per-file linux.sdk.sha1=chromium-autoroll@skia-public.iam.gserviceaccount.com
 per-file mac.sdk.sha1=chromium-autoroll@skia-public.iam.gserviceaccount.com
 per-file linux_internal.sdk.sha1=chromium-internal-autoroll@skia-corp.google.com.iam.gserviceaccount.com
+
+per-file SECURITY_OWNERS=set noparent
+per-file SECURITY_OWNERS=file://build/fuchsia/SECURITY_OWNERS
diff --git a/build/fuchsia/binary_sizes.py b/build/fuchsia/binary_sizes.py
index 72a29648..81a371c9 100755
--- a/build/fuchsia/binary_sizes.py
+++ b/build/fuchsia/binary_sizes.py
@@ -429,7 +429,8 @@
   blob_counts = collections.defaultdict(int)
   for package_name in package_blobs:
     for blob_name in package_blobs[package_name]:
-      blob_counts[blob_name] += 1
+      blob = package_blobs[package_name][blob_name]
+      blob_counts[blob.hash] += 1
 
   # Package sizes are the sum of blob sizes divided by their share counts.
   package_sizes = {}
@@ -439,7 +440,7 @@
     for blob_name in package_blobs[package_name]:
       blob = package_blobs[package_name][blob_name]
       if blob.is_counted:
-        count = blob_counts[blob_name]
+        count = blob_counts[blob.hash]
         compressed_total += blob.compressed // count
         uncompressed_total += blob.uncompressed // count
     package_sizes[package_name] = PackageSizes(compressed_total,
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index d1430cc..17c9271 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -1011,6 +1011,21 @@
         transform_node->needs_local_transform_update = true;
         transform_node->transform_changed = true;
         transform_tree.set_needs_update(true);
+
+        // If the scroll was realized on the compositor, then its transform node
+        // is already updated (see LayerTreeImpl::DidUpdateScrollOffset) and we
+        // are now "catching up" to it on main, so we don't need a commit.
+        //
+        // But if the scroll was NOT realized on the compositor, we need a
+        // commit to push the transform change.
+        //
+        // Skip this if scroll unification is disabled as we will not set
+        // ScrollNode::is_composited in that case.
+        //
+        if (base::FeatureList::IsEnabled(features::kScrollUnification) &&
+            !scroll_tree.CanRealizeScrollsOnCompositor(*scroll_node)) {
+          SetNeedsCommit();
+        }
       }
 
       // The transform tree has been modified which requires a call to
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index c6cd947..67cebfe 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -409,7 +409,6 @@
   "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/DisableablePromoTapCounter.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/EngagementSuppression.java",
-  "java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/QuickAnswersHeuristic.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/RecentScrollTapSuppression.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/RelatedSearchesList.java",
@@ -419,7 +418,6 @@
   "java/src/org/chromium/chrome/browser/contextualsearch/SelectionClientManager.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/ShortTextRunSuppression.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/SmallTextSuppression.java",
-  "java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/TapFarFromPreviousSuppression.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java",
   "java/src/org/chromium/chrome/browser/crash/ChromeMinidumpUploadJobServiceImpl.java",
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBrowserControlsChrome.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBrowserControlsChrome.java
index aeb83e4..f22a7d5 100644
--- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBrowserControlsChrome.java
+++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBrowserControlsChrome.java
@@ -58,14 +58,12 @@
     @Override
     public void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset,
             int bottomOffset, int bottomControlsMinHeightOffset, boolean needsAnimate) {
-        mDelegateObserver.onControlsOffsetChanged(topOffset, topControlsMinHeightOffset,
-                bottomOffset, bottomControlsMinHeightOffset, needsAnimate);
+        mDelegateObserver.onControlsOffsetChanged();
     }
 
     @Override
     public void onBottomControlsHeightChanged(
             int bottomControlsHeight, int bottomControlsMinHeight) {
-        mDelegateObserver.onBottomControlsHeightChanged(
-                bottomControlsHeight, bottomControlsMinHeight);
+        mDelegateObserver.onBottomControlsHeightChanged();
     }
 }
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurface.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurface.java
index 981fc50..da574dc 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurface.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurface.java
@@ -7,13 +7,16 @@
 import android.os.SystemClock;
 import android.view.ViewGroup;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.google.android.material.appbar.AppBarLayout;
 
+import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
+import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherCustomViewManager;
 import org.chromium.chrome.features.tasks.TasksSurface;
 
 /** Interface to communicate with the start surface. */
@@ -253,4 +256,12 @@
      */
     @Nullable
     TasksSurface getPrimaryTasksSurface();
+
+    /**
+     * TODO(crbug.com/1315676): Remove this API after the bug is resolved.
+     *
+     * @return A {@link OneShotSupplier <TabSwitcherCustomViewManager>}.
+     */
+    @NonNull
+    OneshotSupplier<TabSwitcherCustomViewManager> getTabSwitcherCustomViewManagerSupplier();
 }
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
index 62f2dea1..791081f 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
@@ -24,6 +24,7 @@
 import org.chromium.base.ObserverList;
 import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
@@ -47,6 +48,7 @@
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegate.TabSwitcherType;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
+import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherCustomViewManager;
 import org.chromium.chrome.browser.toolbar.top.Toolbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.features.tasks.TasksSurface;
@@ -95,6 +97,9 @@
     private final MenuOrKeyboardActionController mMenuOrKeyboardActionController;
     private final MultiWindowModeStateDispatcher mMultiWindowModeStateDispatcher;
     private final Supplier<Toolbar> mToolbarSupplier;
+    // TODO(crbug.com/1315676): Directly return the supplier from {@link TabSwitcherCoordinator}.
+    private final OneshotSupplierImpl<TabSwitcherCustomViewManager>
+            mTabSwitcherCustomViewManagerSupplier;
 
     @VisibleForTesting
     static final String START_SHOWN_AT_STARTUP_UMA = "Startup.Android.StartSurfaceShownAtStartup";
@@ -258,6 +263,7 @@
         mMultiWindowModeStateDispatcher = multiWindowModeStateDispatcher;
         mToolbarSupplier = toolbarSupplier;
 
+        mTabSwitcherCustomViewManagerSupplier = new OneshotSupplierImpl<>();
         boolean excludeMVTiles = StartSurfaceConfiguration.START_SURFACE_EXCLUDE_MV_TILES.getValue()
                 || !mIsStartSurfaceEnabled;
         boolean excludeQueryTiles =
@@ -270,6 +276,8 @@
                     browserControlsManager, tabCreatorManager, menuOrKeyboardActionController,
                     containerView, shareDelegateSupplier, multiWindowModeStateDispatcher,
                     scrimCoordinator, /* rootView= */ containerView);
+            mTabSwitcherCustomViewManagerSupplier.set(
+                    mTabSwitcher.getTabSwitcherCustomViewManager());
         } else {
             // createSwipeRefreshLayout has to be called before creating any surface.
             createSwipeRefreshLayout();
@@ -498,6 +506,11 @@
         return mTasksSurface;
     }
 
+    @Override
+    public OneshotSupplier<TabSwitcherCustomViewManager> getTabSwitcherCustomViewManagerSupplier() {
+        return mTabSwitcherCustomViewManagerSupplier;
+    }
+
     /**
      * Create the {@link TasksSurface}
      * @param activity The {@link Activity} that creates this surface.
@@ -634,6 +647,11 @@
             mSecondaryTasksSurface.setOnTabSelectingListener(mOnTabSelectingListener);
             mOnTabSelectingListener = null;
         }
+
+        if (!mTabSwitcherCustomViewManagerSupplier.hasValue()) {
+            mTabSwitcherCustomViewManagerSupplier.set(
+                    mSecondaryTasksSurface.getTabSwitcherCustomViewManager());
+        }
         return mSecondaryTasksSurface.getController();
     }
 
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java
index a58beb8..4e9608b 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java
@@ -12,6 +12,7 @@
 import android.view.ViewGroup;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Callback;
@@ -25,6 +26,7 @@
 import org.chromium.chrome.browser.tasks.pseudotab.TabAttributeCache;
 import org.chromium.chrome.browser.tasks.tab_management.TabListFaviconProvider;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
+import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherCustomViewManager;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -151,4 +153,9 @@
         assert false : "should not reach here";
         return null;
     }
+
+    @Override
+    public @Nullable TabSwitcherCustomViewManager getTabSwitcherCustomViewManager() {
+        return null;
+    }
 }
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java
index 875264c..e09771a2 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurface.java
@@ -17,6 +17,7 @@
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.omnibox.OmniboxStub;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
+import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherCustomViewManager;
 
 /**
  * Interface for the Tasks-related Start Surface. The tasks surface displays information related to
@@ -119,4 +120,13 @@
     @VisibleForTesting
     /** Returns whether the MV tiles has been initialized. */
     boolean isMVTilesInitialized();
+
+    /**
+     * TODO(crbug.com/1315676): Remove this API after the bug is resolved.
+     *
+     * @return {@link TabSwitcherCustomViewManager} that allows to pass custom views to {@link
+     *         TabSwitcherCoordinator}.
+     */
+    @Nullable
+    TabSwitcherCustomViewManager getTabSwitcherCustomViewManager();
 }
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
index 58696a7..1ba654624 100644
--- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
@@ -41,6 +41,7 @@
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegate.TabSwitcherType;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
+import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherCustomViewManager;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController;
@@ -293,6 +294,11 @@
         return mIsMVTilesInitialized;
     }
 
+    @Override
+    public @Nullable TabSwitcherCustomViewManager getTabSwitcherCustomViewManager() {
+        return (mTabSwitcher != null) ? mTabSwitcher.getTabSwitcherCustomViewManager() : null;
+    }
+
     /** Suggestions UI Delegate for constructing the TileGroup. */
     private class MostVisitedSuggestionsUiDelegate extends SuggestionsUiDelegateImpl {
         public MostVisitedSuggestionsUiDelegate(SuggestionsNavigationDelegate navigationDelegate,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java
index b0c410dc..bbcb749 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java
@@ -10,6 +10,7 @@
 import android.os.SystemClock;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Callback;
@@ -247,4 +248,11 @@
      * @return {@link Supplier} that provides dialog visibility.
      */
     Supplier<Boolean> getTabGridDialogVisibilitySupplier();
+
+    /**
+     *  @return {@link TabSwitcherCustomViewManager} that allows to pass custom views to {@link
+     *         TabSwitcherCoordinator}.
+     */
+    @Nullable
+    TabSwitcherCustomViewManager getTabSwitcherCustomViewManager();
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
index 909822a..d4b4626 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
@@ -162,6 +162,7 @@
             };
     private TabGridIphDialogCoordinator mTabGridIphDialogCoordinator;
     private PriceTrackingDialogCoordinator mPriceTrackingDialogCoordinator;
+    private TabSwitcherCustomViewManager mTabSwitcherCustomViewManager;
 
     /** {@see TabManagementDelegate#createCarouselTabSwitcher} */
     public TabSwitcherCoordinator(@NonNull Activity activity,
@@ -183,6 +184,20 @@
         mMultiWindowModeStateDispatcher = multiWindowModeStateDispatcher;
         mRootView = rootView;
 
+        mTabSwitcherCustomViewManager =
+                new TabSwitcherCustomViewManager(new TabSwitcherCustomViewManager.Delegate() {
+                    @Override
+                    public void addCustomView(@NonNull View customView) {
+                        // TODO(crbug.com/1227656): Show this custom view in the tab switcher
+                        // content area.
+                    }
+
+                    @Override
+                    public void removeCustomView(@NonNull View customView) {
+                        // TODO(crbug.com/1227656): Release this custom view from the tab switcher
+                        // content area and show the previously showed contents.
+                    }
+                });
         PropertyModel containerViewModel = new PropertyModel(TabListContainerProperties.ALL_KEYS);
 
         mMediator = new TabSwitcherMediator(activity, this, containerViewModel, tabModelSelector,
@@ -436,6 +451,11 @@
     }
 
     @Override
+    public TabSwitcherCustomViewManager getTabSwitcherCustomViewManager() {
+        return mTabSwitcherCustomViewManager;
+    }
+
+    @Override
     public int getTabListTopOffset() {
         return mTabListCoordinator.getTabListTopOffset();
     }
diff --git a/chrome/android/java/res/drawable-night/virtual_card_enrollment_illustration.xml b/chrome/android/java/res/drawable-night/virtual_card_enrollment_illustration.xml
index c509f34..00ff94b 100644
--- a/chrome/android/java/res/drawable-night/virtual_card_enrollment_illustration.xml
+++ b/chrome/android/java/res/drawable-night/virtual_card_enrollment_illustration.xml
@@ -4,49 +4,49 @@
      found in the LICENSE file. -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="125dp"
-    android:height="88dp"
-    android:viewportWidth="125"
-    android:viewportHeight="88">
+    android:width="114dp"
+    android:height="80dp"
+    android:viewportWidth="114"
+    android:viewportHeight="80">
   <path
-      android:strokeWidth="1"
-      android:pathData="M0.584,68.234C0.584,69.471 1.587,70.474 2.824,70.474H83.67C84.906,70.474 85.91,69.471 85.91,68.234V19.795C85.91,18.558 84.906,17.555 83.67,17.555H2.824C1.587,17.555 0.584,18.558 0.584,19.795V68.234Z"
+      android:pathData="M0.545,62.03C0.545,63.154 1.457,64.066 2.581,64.066H76.077C77.201,64.066 78.114,63.154 78.114,62.03V17.994C78.114,16.87 77.201,15.958 76.077,15.958H2.581C1.457,15.958 0.545,16.87 0.545,17.994V62.03Z"
+      android:strokeWidth="0.909091"
       android:fillColor="#9AA0A6"
       android:strokeColor="#9AA0A6"/>
   <path
-      android:pathData="M72.032,54.814H12.966C11.724,54.814 10.721,53.811 10.721,52.569V51.522C10.721,50.281 11.724,49.277 12.966,49.277H72.032C73.274,49.277 74.277,50.281 74.277,51.522V52.569C74.27,53.811 73.266,54.814 72.032,54.814Z"
+      android:pathData="M65.499,49.83H11.803C10.674,49.83 9.762,48.918 9.762,47.789V46.838C9.762,45.709 10.674,44.797 11.803,44.797H65.499C66.628,44.797 67.54,45.709 67.54,46.838V47.789C67.534,48.918 66.622,49.83 65.499,49.83Z"
       android:fillColor="#BDC1C6"/>
   <path
-      android:pathData="M16.734,41.986H8.866C7.66,41.986 6.686,41.011 6.686,39.806V34.825C6.686,33.619 7.66,32.645 8.866,32.645H16.734C17.94,32.645 18.915,33.619 18.915,34.825V39.806C18.915,41.011 17.94,41.986 16.734,41.986Z"
+      android:pathData="M15.229,38.168H8.075C6.979,38.168 6.093,37.283 6.093,36.187V31.658C6.093,30.562 6.979,29.676 8.075,29.676H15.229C16.325,29.676 17.211,30.562 17.211,31.658V36.187C17.211,37.283 16.325,38.168 15.229,38.168Z"
       android:fillColor="#BDC1C6"/>
   <path
-      android:pathData="M23.737,63.513H12.641C11.58,63.513 10.721,62.654 10.721,61.593V59.896C10.721,58.835 11.58,57.976 12.641,57.976H23.737C24.798,57.976 25.657,58.835 25.657,59.896V61.593C25.657,62.654 24.798,63.513 23.737,63.513Z"
+      android:pathData="M21.594,57.738H11.508C10.543,57.738 9.762,56.957 9.762,55.993V54.451C9.762,53.486 10.543,52.705 11.508,52.705H21.594C22.559,52.705 23.34,53.486 23.34,54.451V55.993C23.34,56.957 22.559,57.738 21.594,57.738Z"
       android:fillColor="#BDC1C6"/>
   <path
       android:strokeWidth="1"
-      android:pathData="M10.217,32.645V41.986"
+      android:pathData="M9.302,29.676V38.168"
       android:fillColor="#00000000"
       android:strokeColor="#9AA0A6"/>
   <path
       android:strokeWidth="1"
-      android:pathData="M18.915,37.315H6.693"
+      android:pathData="M17.211,33.922H6.1"
       android:fillColor="#00000000"
       android:strokeColor="#9AA0A6"/>
   <path
-      android:pathData="M75.771,88C100.072,88 119.771,68.3 119.771,44C119.771,19.699 100.072,0 75.771,0C51.471,0 31.771,19.699 31.771,44C31.771,68.3 51.471,88 75.771,88Z"
-      android:fillColor="#185ABC"/>
+      android:pathData="M68.899,80C90.991,80 108.899,62.091 108.899,40C108.899,17.909 90.991,0 68.899,0C46.808,0 28.899,17.909 28.899,40C28.899,62.091 46.808,80 68.899,80Z"
+      android:fillColor="#174EA6"/>
   <path
-      android:pathData="M83.67,16.972H41.07C35.252,24.429 31.779,33.807 31.779,44C31.779,54.208 35.266,63.592 41.099,71.057H83.677C85.236,71.057 86.5,69.794 86.5,68.234V19.795C86.492,18.235 85.229,16.972 83.67,16.972Z"
+      android:pathData="M76.079,15.429H37.353C32.063,22.208 28.906,30.733 28.906,40C28.906,49.279 32.076,57.811 37.379,64.597H76.086C77.504,64.597 78.652,63.448 78.652,62.031V17.994C78.645,16.577 77.497,15.429 76.079,15.429Z"
       android:fillColor="#4285F4"/>
   <path
-      android:pathData="M92.059,41.849L101.941,51.732L123.981,29.685"
+      android:pathData="M83.705,38.044L92.69,47.028L112.726,26.986"
       android:strokeLineJoin="round"
       android:strokeWidth="2"
       android:fillColor="#00000000"
       android:strokeColor="#34A853"
       android:strokeLineCap="round"/>
   <path
-      android:pathData="M60.512,29.778L71.586,34.702V42.138C71.586,49.292 66.871,55.882 60.512,57.846C54.152,55.882 49.438,49.284 49.438,42.138V34.702L60.512,29.778Z"
+      android:pathData="M55.026,27.071L65.093,31.547V38.307C65.093,44.811 60.808,50.802 55.026,52.587C49.244,50.802 44.959,44.804 44.959,38.307V31.547L55.026,27.071Z"
       android:strokeLineJoin="round"
       android:strokeWidth="2"
       android:fillColor="#00000000"
diff --git a/chrome/android/java/res/drawable/virtual_card_enrollment_illustration.xml b/chrome/android/java/res/drawable/virtual_card_enrollment_illustration.xml
index 35053c2..539ea3aa 100644
--- a/chrome/android/java/res/drawable/virtual_card_enrollment_illustration.xml
+++ b/chrome/android/java/res/drawable/virtual_card_enrollment_illustration.xml
@@ -4,54 +4,52 @@
      found in the LICENSE file. -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="130dp"
-    android:height="92dp"
-    android:viewportWidth="130"
-    android:viewportHeight="92">
-  <group>
-    <clip-path
-        android:pathData="M0,0h130v91.467h-130z"/>
-    <path
-        android:pathData="M86.972,73.862H2.934C1.313,73.862 0,72.549 0,70.928V20.576C0,18.955 1.313,17.642 2.934,17.642H86.972C88.593,17.642 89.906,18.955 89.906,20.576V70.928C89.906,72.549 88.593,73.862 86.972,73.862Z"
-        android:fillColor="#DADCE0"/>
-    <path
-        android:pathData="M74.875,56.978H13.477C12.187,56.978 11.144,55.935 11.144,54.645V53.556C11.144,52.266 12.187,51.223 13.477,51.223H74.875C76.166,51.223 77.209,52.266 77.209,53.556V54.645C77.202,55.935 76.159,56.978 74.875,56.978Z"
-        android:fillColor="#E8EAED"/>
-    <path
-        android:pathData="M17.395,43.644H9.215C7.962,43.644 6.949,42.631 6.949,41.377V36.2C6.949,34.946 7.962,33.933 9.215,33.933H17.395C18.648,33.933 19.661,34.946 19.661,36.2V41.377C19.661,42.631 18.648,43.644 17.395,43.644Z"
-        android:fillColor="#E8EAED"/>
-    <path
-        android:pathData="M24.673,66.021H13.14C12.036,66.021 11.144,65.128 11.144,64.024V62.261C11.144,61.158 12.036,60.265 13.14,60.265H24.673C25.776,60.265 26.669,61.158 26.669,62.261V64.024C26.669,65.128 25.776,66.021 24.673,66.021Z"
-        android:fillColor="#E8EAED"/>
-    <path
-        android:pathData="M10.618,33.933V43.644"
-        android:strokeWidth="0.750404"
-        android:fillColor="#00000000"
-        android:strokeColor="#DADCE0"/>
-    <path
-        android:pathData="M19.66,38.788H6.956"
-        android:strokeWidth="0.858462"
-        android:fillColor="#00000000"
-        android:strokeColor="#DADCE0"/>
-    <path
-        android:pathData="M78.762,91.474C104.022,91.474 124.5,70.997 124.5,45.737C124.5,20.477 104.022,0 78.762,0C53.503,0 33.025,20.477 33.025,45.737C33.025,70.997 53.503,91.474 78.762,91.474Z"
-        android:fillColor="#D2E3FC"/>
-    <path
-        android:pathData="M86.972,17.642H42.691C36.643,25.394 33.033,35.141 33.033,45.737C33.033,56.348 36.658,66.103 42.721,73.862H86.98C88.601,73.862 89.914,72.549 89.914,70.928V20.576C89.906,18.955 88.593,17.642 86.972,17.642Z"
-        android:fillColor="#4285F4"/>
-    <path
-        android:pathData="M95.691,43.501L105.964,53.774L128.874,30.857"
-        android:strokeLineJoin="round"
-        android:strokeWidth="2.25121"
-        android:fillColor="#00000000"
-        android:strokeColor="#34A853"
-        android:strokeLineCap="round"/>
-    <path
-        android:pathData="M65.51,30.779L76.585,35.702V43.138C76.585,50.292 71.87,56.883 65.51,58.846C59.151,56.883 54.437,50.284 54.437,43.138V35.702L65.51,30.779Z"
-        android:strokeLineJoin="round"
-        android:strokeWidth="2.38113"
-        android:fillColor="#00000000"
-        android:strokeColor="#ffffff"
-        android:strokeLineCap="round"/>
-  </group>
+    android:width="114dp"
+    android:height="80dp"
+    android:viewportWidth="114"
+    android:viewportHeight="80">
+  <path
+      android:pathData="M0.545,62.03C0.545,63.154 1.457,64.066 2.581,64.066H76.077C77.201,64.066 78.114,63.154 78.114,62.03V17.994C78.114,16.87 77.201,15.958 76.077,15.958H2.581C1.457,15.958 0.545,16.87 0.545,17.994V62.03Z"
+      android:strokeWidth="0.909091"
+      android:fillColor="#DADCE0"
+      android:strokeColor="#DADCE0"/>
+  <path
+      android:pathData="M65.499,49.83H11.803C10.674,49.83 9.762,48.918 9.762,47.789V46.838C9.762,45.709 10.674,44.797 11.803,44.797H65.499C66.628,44.797 67.54,45.709 67.54,46.838V47.789C67.534,48.918 66.622,49.83 65.499,49.83Z"
+      android:fillColor="#E8EAED"/>
+  <path
+      android:pathData="M15.229,38.168H8.075C6.979,38.168 6.093,37.283 6.093,36.187V31.658C6.093,30.562 6.979,29.676 8.075,29.676H15.229C16.325,29.676 17.211,30.562 17.211,31.658V36.187C17.211,37.283 16.325,38.168 15.229,38.168Z"
+      android:fillColor="#E8EAED"/>
+  <path
+      android:pathData="M21.594,57.738H11.508C10.543,57.738 9.762,56.957 9.762,55.993V54.45C9.762,53.486 10.543,52.705 11.508,52.705H21.594C22.559,52.705 23.34,53.486 23.34,54.45V55.993C23.34,56.957 22.559,57.738 21.594,57.738Z"
+      android:fillColor="#E8EAED"/>
+  <path
+      android:strokeWidth="1"
+      android:pathData="M9.302,29.676V38.168"
+      android:fillColor="#00000000"
+      android:strokeColor="#DADCE0"/>
+  <path
+      android:strokeWidth="1"
+      android:pathData="M17.211,33.922H6.1"
+      android:fillColor="#00000000"
+      android:strokeColor="#DADCE0"/>
+  <path
+      android:pathData="M68.899,80C90.991,80 108.899,62.091 108.899,40C108.899,17.909 90.991,0 68.899,0C46.808,0 28.899,17.909 28.899,40C28.899,62.091 46.808,80 68.899,80Z"
+      android:fillColor="#D2E3FC"/>
+  <path
+      android:pathData="M76.079,15.429H37.353C32.063,22.208 28.906,30.733 28.906,40C28.906,49.279 32.076,57.811 37.379,64.597H76.086C77.504,64.597 78.652,63.448 78.652,62.031V17.994C78.645,16.577 77.497,15.429 76.079,15.429Z"
+      android:fillColor="#4285F4"/>
+  <path
+      android:pathData="M83.705,38.044L92.69,47.028L112.726,26.986"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="#34A853"
+      android:strokeLineCap="round"/>
+  <path
+      android:pathData="M55.026,27.071L65.093,31.547V38.307C65.093,44.811 60.808,50.802 55.026,52.587C49.244,50.802 44.959,44.804 44.959,38.307V31.547L55.026,27.071Z"
+      android:strokeLineJoin="round"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="#ffffff"
+      android:strokeLineCap="round"/>
 </vector>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java
index 2ae5799..1cc69f62 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java
@@ -332,7 +332,7 @@
     }
 
     /**
-     * Pushes the given language down to the native ContextualSearchContext.
+     * Pushes the given languages down to the native ContextualSearchContext.
      * @param detectedLanguage An ISO 639 language code string for the language to translate from.
      * @param targetLanguage An ISO 639 language code string to translation into.
      * @param fluentLanguages An ordered comma-separated list of ISO 639 language codes that
@@ -343,10 +343,9 @@
             @NonNull String fluentLanguages) {
         // Set redundant languages to empty strings.
         fluentLanguages = targetLanguage.equals(fluentLanguages) ? "" : fluentLanguages;
-        if (targetLanguage.equals(detectedLanguage)) {
-            detectedLanguage = "";
-            targetLanguage = "";
-        }
+        // The target language is essential in order to provide results the user can read, and if
+        // not specified the server may fallback onto a guess based on location, which isn't
+        // always a good experience.
         ContextualSearchContextJni.get().setTranslationLanguages(
                 mNativePointer, this, detectedLanguage, targetLanguage, fluentLanguages);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
index 364f225..eb917d7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -211,6 +211,7 @@
          */
         int MANDATORY_PROMO_LIMIT = 0;
         /**
+         * @deprecated
          * A Y value limit that will suppress a Tap near the top of the screen.
          * (any Y value less than the limit will suppress the Tap trigger).
          */
@@ -225,6 +226,7 @@
          */
         int WAIT_AFTER_TAP_DELAY_MS = 3;
         /**
+         * @deprecated
          * A threshold for the duration of a tap gesture for categorization as brief or
          * lengthy (the maximum amount of time in milliseconds for a tap gesture that's still
          * considered a very brief duration tap).
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java
index b6e9317..06d8fdc9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java
@@ -189,15 +189,14 @@
     }
 
     /**
-     * Adds translation parameters, unless they match.
+     * Adds translation parameters.
      * @param sourceLanguage The language of the original search term.
      * @param targetLanguage The language the that the user prefers.
      */
     void forceTranslation(String sourceLanguage, String targetLanguage) {
         mIsTranslationForced = true;
         // If the server is providing a full URL then we shouldn't alter it.
-        if (mIsFullSearchUrlProvided || TextUtils.isEmpty(targetLanguage)
-                || targetLanguage.equals(sourceLanguage)) {
+        if (mIsFullSearchUrlProvided || TextUtils.isEmpty(targetLanguage)) {
             return;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
index 8ae763a..6e3ffd1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
@@ -12,7 +12,6 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.Log;
-import org.chromium.base.TimeUtils;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting;
@@ -61,10 +60,6 @@
     // Max selection length must be limited or the entire request URL can go past the 2K limit.
     private static final int MAX_SELECTION_LENGTH = 1000;
 
-    private static final int INVALID_DURATION = -1;
-    // A default tap duration value when we can't compute it.
-    private static final int DEFAULT_DURATION = 0;
-
     private final Activity mActivity;
     private final ContextualSearchSelectionHandler mHandler;
     private final float mPxToDp;
@@ -114,9 +109,6 @@
     // Whether the selection was empty before the most recent tap gesture.
     private boolean mWasSelectionEmptyBeforeTap;
 
-    // The duration of the last tap gesture in milliseconds, or 0 if not set.
-    private int mTapDurationMs = INVALID_DURATION;
-
     /** Tracks whether we're currently clearing the selection to prevent recursion. */
     private boolean mClearingSelection;
 
@@ -410,7 +402,6 @@
         mLastTapState = null;
         mLastScrollTimeNs = 0;
         mTapTimeNanoseconds = 0;
-        mTapDurationMs = INVALID_DURATION;
         mDidExpandSelection = false;
         mFontSizeDips = 0;
         mTextRunLength = 0;
@@ -450,10 +441,6 @@
         if (mSelectionType != SelectionType.LONG_PRESS && !mAreSelectionHandlesShown
                 && mLastValidSelectionType != SelectionType.LONG_PRESS
                 && mLastValidSelectionType != SelectionType.RESOLVING_LONG_PRESS) {
-            if (mTapTimeNanoseconds != 0) {
-                mTapDurationMs = (int) ((System.nanoTime() - mTapTimeNanoseconds)
-                        / TimeUtils.NANOSECONDS_PER_MILLISECOND);
-            }
             mWasTapGestureDetected = true;
             mSelectionType = SelectionType.TAP;
             mX = x;
@@ -482,11 +469,9 @@
         int x = (int) mX;
         int y = (int) mY;
 
-        // TODO(donnd): Remove tap counters.
-        if (mTapDurationMs == INVALID_DURATION) mTapDurationMs = DEFAULT_DURATION;
         TapSuppressionHeuristics tapHeuristics =
                 new TapSuppressionHeuristics(this, mLastTapState, x, y, contextualSearchContext,
-                        mTapDurationMs, mWasSelectionEmptyBeforeTap, mFontSizeDips, mTextRunLength);
+                        mWasSelectionEmptyBeforeTap, mFontSizeDips, mTextRunLength);
         // TODO(donnd): Move to be called when the panel closes to work with states that change.
         tapHeuristics.logConditionState();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
index 8b6f5bb..015c832 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
@@ -517,73 +517,6 @@
     }
 
     /**
-     * Logs the location of a Tap and whether the panel was seen and the type of the
-     * trigger.
-     * @param wasPanelSeen Whether the panel was seen.
-     * @param wasTap Whether the gesture was a Tap or not.
-     * @param triggerLocationDps The trigger location from the top of the screen.
-     */
-    public static void logScreenTopTapLocation(
-            boolean wasPanelSeen, boolean wasTap, int triggerLocationDps) {
-        // We only log Tap locations for the screen top.
-        if (!wasTap) return;
-        String histogram = wasPanelSeen ? "Search.ContextualSearchTopLocationSeen"
-                                        : "Search.ContextualSearchTopLocationNotSeen";
-        int min = 1;
-        int max = 250;
-        int numBuckets = 50;
-        RecordHistogram.recordCustomCountHistogram(
-                histogram, triggerLocationDps, min, max, numBuckets);
-    }
-
-    /**
-     * Log whether the UX was suppressed due to a Tap too close to the screen top.
-     * @param wasSuppressed Whether showing the UX was suppressed.
-     */
-    public static void logScreenTopTapSuppression(boolean wasSuppressed) {
-        RecordHistogram.recordBooleanHistogram(
-                "Search.ContextualSearchScreenTopSuppressed", wasSuppressed);
-    }
-
-    /**
-     * Logs whether results were seen based on the duration of the Tap, for both short and long
-     * durations.
-     * @param wasSearchContentViewSeen If the panel was opened.
-     * @param isTapShort Whether this tap was "short" in duration.
-     */
-    public static void logTapDurationSeen(boolean wasSearchContentViewSeen, boolean isTapShort) {
-        if (isTapShort) {
-            RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchTapShortDurationSeen",
-                    wasSearchContentViewSeen ? Results.SEEN : Results.NOT_SEEN,
-                    Results.NUM_ENTRIES);
-        } else {
-            RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchTapLongDurationSeen",
-                    wasSearchContentViewSeen ? Results.SEEN : Results.NOT_SEEN,
-                    Results.NUM_ENTRIES);
-        }
-    }
-
-    /**
-     * Logs the duration of a Tap in ms into custom histograms to profile the duration of seen
-     * and not seen taps.
-     * @param wasPanelSeen Whether the panel was seen.
-     * @param durationMs The duration of the tap gesture.
-     */
-    public static void logTapDuration(boolean wasPanelSeen, int durationMs) {
-        int min = 1;
-        int max = 1000;
-        int numBuckets = 100;
-
-        if (wasPanelSeen) {
-            RecordHistogram.recordCustomCountHistogram(
-                    "Search.ContextualSearchTapDurationSeen", durationMs, min, max, numBuckets);
-        } else {
-            RecordHistogram.recordCustomCountHistogram(
-                    "Search.ContextualSearchTapDurationNotSeen", durationMs, min, max, numBuckets);
-        }
-    }
-
-    /**
      * Log whether results were seen due to a Tap on what we've recognized as a probable entity.
      * @param wasSearchContentViewSeen If the panel was opened.
      * @param isWordAnEntity Whether this tap was on a word that's an entity.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java
deleted file mode 100644
index 0db8fa5..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/NearTopTapSuppression.java
+++ /dev/null
@@ -1,60 +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.
-
-package org.chromium.chrome.browser.contextualsearch;
-
-import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting;
-
-/**
- * Provides a {@link ContextualSearchHeuristic} for Tap suppression for any tap near the top of the
- * content view area.
- * Handles logging of results seen and the condition state.
- */
-public class NearTopTapSuppression extends ContextualSearchHeuristic {
-    private final int mExperiementThresholdDps;
-    private final boolean mIsConditionSatisfied;
-    private final int mYDp;
-
-    /**
-     * Constructs a Tap suppression heuristic that handles a Tap after a recent scroll.
-     * This logs activation data that includes whether it activated for a threshold specified
-     * by an experiment. This also logs Results-seen data to profile when results are seen relative
-     * to a recent scroll.
-     * @param selectionController The {@link ContextualSearchSelectionController}.
-     */
-    NearTopTapSuppression(ContextualSearchSelectionController selectionController, int y) {
-        mExperiementThresholdDps = ContextualSearchFieldTrial.getValue(
-                ContextualSearchSetting.SCREEN_TOP_SUPPRESSION_DPS);
-        mYDp = (int) (y * selectionController.getPxToDp());
-        mIsConditionSatisfied = mYDp < mExperiementThresholdDps;
-    }
-
-    @Override
-    protected boolean isConditionSatisfiedAndEnabled() {
-        return mIsConditionSatisfied;
-    }
-
-    @Override
-    protected void logConditionState() {
-        if (mExperiementThresholdDps > 0) {
-            ContextualSearchUma.logScreenTopTapSuppression(mIsConditionSatisfied);
-        }
-    }
-
-    @Override
-    protected void logResultsSeen(boolean wasSearchContentViewSeen, boolean wasActivatedByTap) {
-        if (wasActivatedByTap) {
-            ContextualSearchUma.logScreenTopTapLocation(
-                    wasSearchContentViewSeen, wasActivatedByTap, mYDp);
-        }
-    }
-
-    @Override
-    protected void logRankerTapSuppression(ContextualSearchInteractionRecorder logger) {
-        logger.logFeature(ContextualSearchInteractionRecorder.Feature.SCREEN_TOP_DPS, mYDp);
-    }
-
-    // TODO(twellington): Define a default value to use when determining if the condition is
-    // satisfied for logging.
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java
deleted file mode 100644
index 0c6391c..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java
+++ /dev/null
@@ -1,64 +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.
-
-package org.chromium.chrome.browser.contextualsearch;
-
-import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting;
-
-/**
- * Provides a {@link ContextualSearchHeuristic} for the duration of a Tap being either brief or
- * lengthy. This signal could be used for suppression of taps below some threshold, so we
- * aggregate-log too. We log CTR to UMA for Taps shorter and longer than the threshold.
- */
-class TapDurationSuppression extends ContextualSearchHeuristic {
-    private static final int DEFAULT_TAP_DURATION_THRESHOLD_MS = 70;
-
-    private final int mTapDurationMs;
-    private final int mTapDurationThresholdMs;
-    private final boolean mIsConditionSatisfied;
-
-    /**
-     * Constructs a heuristic to categorize the Tap based on duration as either short or long.
-     * @param tapDurationMs The duration of the tap in milliseconds.
-     */
-    TapDurationSuppression(int tapDurationMs) {
-        mTapDurationMs = tapDurationMs;
-        mTapDurationThresholdMs = ContextualSearchFieldTrial.getValue(
-                ContextualSearchSetting.TAP_DURATION_THRESHOLD_MS);
-        int tapDurationThreshold = mTapDurationThresholdMs != 0 ? mTapDurationThresholdMs
-                                                                : DEFAULT_TAP_DURATION_THRESHOLD_MS;
-        mIsConditionSatisfied = tapDurationMs < tapDurationThreshold;
-    }
-
-    @Override
-    protected boolean isConditionSatisfiedAndEnabled() {
-        return mIsConditionSatisfied && mTapDurationThresholdMs != 0;
-    }
-
-    @Override
-    protected void logResultsSeen(boolean wasSearchContentViewSeen, boolean wasActivatedByTap) {
-        if (wasActivatedByTap) {
-            ContextualSearchUma.logTapDurationSeen(wasSearchContentViewSeen, mIsConditionSatisfied);
-
-            // TODO(donnd): remove when these histograms have been analyzed.
-            ContextualSearchUma.logTapDuration(wasSearchContentViewSeen, mTapDurationMs);
-        }
-    }
-
-    @Override
-    protected void logRankerTapSuppression(ContextualSearchInteractionRecorder logger) {
-        logger.logFeature(
-                ContextualSearchInteractionRecorder.Feature.TAP_DURATION_MS, mTapDurationMs);
-    }
-
-    @Override
-    protected boolean shouldAggregateLogForTapSuppression() {
-        return true;
-    }
-
-    @Override
-    protected boolean isConditionSatisfiedForAggregateLogging() {
-        return mIsConditionSatisfied;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java
index fe97b22..46a9576 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java
@@ -18,23 +18,20 @@
      * @param x The x position of the Tap.
      * @param y The y position of the Tap.
      * @param contextualSearchContext The {@link ContextualSearchContext} of this tap.
-     * @param tapDurationMs The duration of this tap in milliseconds.
      * @param wasSelectionEmptyBeforeTap Whether the selection was empty before this tap.
      * @param fontSizeDips The font size from Blink in dips.
      * @param elementRunLength The length of the text in the element tapped, in characters.
      */
     TapSuppressionHeuristics(ContextualSearchSelectionController selectionController,
             @Nullable ContextualSearchTapState previousTapState, int x, int y,
-            ContextualSearchContext contextualSearchContext, int tapDurationMs,
-            boolean wasSelectionEmptyBeforeTap, int fontSizeDips, int elementRunLength) {
+            ContextualSearchContext contextualSearchContext, boolean wasSelectionEmptyBeforeTap,
+            int fontSizeDips, int elementRunLength) {
         super();
         mHeuristics.add(new EngagementSuppression());
         mHeuristics.add(new RecentScrollTapSuppression(selectionController));
         mHeuristics.add(new TapFarFromPreviousSuppression(
                 selectionController, previousTapState, x, y, wasSelectionEmptyBeforeTap));
-        mHeuristics.add(new TapDurationSuppression(tapDurationMs));
         mHeuristics.add(new ContextualSearchEntityHeuristic(contextualSearchContext));
-        mHeuristics.add(new NearTopTapSuppression(selectionController, y));
         mHeuristics.add(new ShortTextRunSuppression(contextualSearchContext, elementRunLength));
         mHeuristics.add(new SmallTextSuppression(fontSizeDips));
         // Quick Answer that appears in the Caption via the JS API.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentAppComparator.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentAppComparator.java
index a3193a95..6bb2f3a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentAppComparator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentAppComparator.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.payments.ui;
 
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.payments.PaymentPreferencesUtil;
 import org.chromium.components.autofill.Completable;
 import org.chromium.components.payments.PaymentApp;
@@ -12,8 +13,10 @@
 import org.chromium.payments.mojom.PaymentOptions;
 
 import java.util.Comparator;
-
-/** A comparator that is used to rank the payment apps to be listed on the PaymentRequest UI. */
+/**
+   A comparator that is used to rank the payment apps to be listed on the PaymentRequest
+   UI.
+ */
 /* package */ class PaymentAppComparator implements Comparator<PaymentApp> {
     private final PaymentRequestParams mParams;
 
@@ -26,18 +29,18 @@
     }
 
     /**
-     * Compares two payment apps by frecency.
-     * Return negative value if a has strictly lower frecency score than b.
-     * Return zero if a and b have the same frecency score.
-     * Return positive value if a has strictly higher frecency score than b.
+     * Compares two payment apps by ranking score.
+     * Return negative value if a has strictly lower ranking score than b.
+     * Return zero if a and b have the same ranking score.
+     * Return positive value if a has strictly higher ranking score than b.
      */
-    private static int compareAppsByFrecency(PaymentApp a, PaymentApp b) {
+    private static int compareAppsByRankingScore(PaymentApp a, PaymentApp b) {
         int aCount = PaymentPreferencesUtil.getPaymentAppUseCount(a.getIdentifier());
         int bCount = PaymentPreferencesUtil.getPaymentAppUseCount(b.getIdentifier());
         long aDate = PaymentPreferencesUtil.getPaymentAppLastUseDate(a.getIdentifier());
         long bDate = PaymentPreferencesUtil.getPaymentAppLastUseDate(a.getIdentifier());
 
-        return Double.compare(getFrecencyScore(aCount, aDate), getFrecencyScore(bCount, bDate));
+        return Double.compare(getRankingScore(aCount, aDate), getRankingScore(bCount, bDate));
     }
 
     /**
@@ -51,11 +54,29 @@
     }
 
     /**
-     * The frecency score is calculated according to use count and last use date. The formula is
-     * the same as the one used in GetFrecencyScore in autofill_data_model.cc.
+     * The ranking score is calculated according to use count and last use date. The formula is
+     * the same as the one used in GetRankingScore in autofill_data_model.cc.
      */
-    private static double getFrecencyScore(int count, long date) {
+    private static double getRankingScore(int count, long date) {
         long currentTime = System.currentTimeMillis();
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.AUTOFILL_ENABLE_RANKING_FORMULA)) {
+            int usageHalfLife = ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
+                    ChromeFeatureList.AUTOFILL_ENABLE_RANKING_FORMULA,
+                    ChromeFeatureList.AUTOFILL_RANKING_FORMULA_USAGE_HALF_LIFE, 20);
+
+            // Ensure the usage half life is not zero to avoid division by zero errors;
+            if (usageHalfLife == 0) {
+                // Set to default value of 20.
+                usageHalfLife = 20;
+            }
+
+            // Exponentially decay the use count by the days since the data model was
+            // last used.
+            return Math.log10(count + 1)
+                    * Math.exp(((currentTime - date) / (24 * 60 * 60 * 1000)) / usageHalfLife);
+        }
+
+        // Default to legacy frecency scoring.
         return -Math.log((currentTime - date) / (24 * 60 * 60 * 1000) + 2) / Math.log(count + 2);
     }
 
@@ -119,6 +140,6 @@
         if (canPreselect != 0) return canPreselect;
 
         // More frequently and recently used apps first.
-        return compareAppsByFrecency(b, a);
+        return compareAppsByRankingScore(b, a);
     }
 }
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java
index 7c49c1c..c521146 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java
@@ -142,6 +142,7 @@
         if (noPreviousHistory) {
             // If this is the first time we make a decision, don't show query tiles.
             resultFromCode = false;
+            updateDisplayStatusAndNextDecisionTime(resultFromCode);
         } else if (nextDecisionTimestampReached) {
             int recentMVClicks = SharedPreferencesManager.getInstance().readInt(
                     ChromePreferenceKeys.QUERY_TILES_NUM_RECENT_MV_TILE_CLICKS, 0);
@@ -155,6 +156,7 @@
             // Otherwise, show it for a period of time.
             resultFromCode = (recentMVClicks <= mvTileClickThreshold
                     || recentMVClicks <= recentQueryTileClicks);
+            updateDisplayStatusAndNextDecisionTime(resultFromCode);
         } else {
             resultFromCode = SharedPreferencesManager.getInstance().readBoolean(
                     ChromePreferenceKeys.QUERY_TILES_SHOW_ON_NTP, false);
@@ -166,7 +168,6 @@
             recordSegmentationResultComparison(getSegmentationResult(), resultFromCode);
         }
 
-        updateDisplayStatusAndNextDecisionTime(resultFromCode);
         return resultFromCode;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
index 7c118ea..7564a02 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -65,6 +65,7 @@
 import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthController;
 import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthCoordinatorFactory;
 import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager;
+import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthTabSwitcherDelegate;
 import org.chromium.chrome.browser.layouts.LayoutManager;
 import org.chromium.chrome.browser.layouts.LayoutStateProvider;
 import org.chromium.chrome.browser.layouts.LayoutType;
@@ -101,6 +102,7 @@
 import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tasks.tab_management.TabSwitcherCustomViewManager;
 import org.chromium.chrome.browser.theme.TopUiThemeColorProvider;
 import org.chromium.chrome.browser.toolbar.ButtonDataProvider;
 import org.chromium.chrome.browser.toolbar.ToolbarIntentMetadata;
@@ -193,6 +195,11 @@
      * available.
      */
     private @Nullable IncognitoReauthController mIncognitoReauthController;
+    /**
+     * A Callback controller that is fired when the {@link TabSwitcherCustomViewManager} is made
+     * available.
+     */
+    private @Nullable CallbackController mTabSwitcherCustomViewController;
 
     /** A means of providing the theme color to different features. */
     private TopUiThemeColorProvider mTopUiThemeColorProvider;
@@ -571,6 +578,10 @@
             mIncognitoReauthController.destroy();
         }
 
+        if (mTabSwitcherCustomViewController != null) {
+            mTabSwitcherCustomViewController.destroy();
+        }
+
         mActivity = null;
     }
 
@@ -704,9 +715,33 @@
 
         if (IncognitoReauthManager.isIncognitoReauthFeatureAvailable()) {
             TabModelSelector tabModelSelector = mTabModelSelectorSupplier.get();
+            // TODO(crbug.com/1324211, crbug.com/1227656) : Refactor below to remove
+            //  IncognitoReauthTabSwitcherDelegate altogether and directly pass
+            //  OneshotSupplierImpl<TabSwitcherCustomViewManager> instance.
+            OneshotSupplierImpl<IncognitoReauthTabSwitcherDelegate>
+                    incognitoReauthTabSwitcherSupplier = new OneshotSupplierImpl<>();
+            mTabSwitcherCustomViewController = new CallbackController();
+            mStartSurfaceSupplier.get().getTabSwitcherCustomViewManagerSupplier().onAvailable(
+                    mTabSwitcherCustomViewController.makeCancelable(tabSwitcherCustomViewManager
+                            -> incognitoReauthTabSwitcherSupplier.set(
+                                    new IncognitoReauthTabSwitcherDelegate() {
+                                        @Override
+                                        public boolean addReauthScreenInTabSwitcher(
+                                                @NonNull View customView) {
+                                            return tabSwitcherCustomViewManager.requestView(
+                                                    customView);
+                                        }
+
+                                        @Override
+                                        public boolean removeReauthScreenFromTabSwitcher() {
+                                            return tabSwitcherCustomViewManager.releaseView();
+                                        }
+                                    })));
+
             IncognitoReauthCoordinatorFactory incognitoReauthCoordinatorFactory =
                     new IncognitoReauthCoordinatorFactory(mActivity, tabModelSelector,
-                            mModalDialogManagerSupplier.get(), new SettingsLauncherImpl());
+                            mModalDialogManagerSupplier.get(), new SettingsLauncherImpl(),
+                            incognitoReauthTabSwitcherSupplier);
             mIncognitoReauthController = new IncognitoReauthController(tabModelSelector,
                     mActivityLifecycleDispatcher, mLayoutStateProviderOneShotSupplier,
                     mProfileSupplier, incognitoReauthCoordinatorFactory);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 8ffc117..12d93db4 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5668,19 +5668,19 @@
         Google Password Manager
       </message>
       <message name="IDS_PASSWORD_BUBBLES_FOOTER_SYNCED_TO_ACCOUNT" desc="The footer text of the bubbles that offers users to save, update or manage stored passwords in Chrome and synced to their Google account.">
-        You can use saved passwords on any device. They're saved to <ph name="GOOGLE_PASSWORD_MANAGER">$1<ex>Google Password Manager</ex></ph> for <ph name="EMAIL">$2<ex>user@gmail.com</ex></ph>
+        You can use saved passwords on any device. They're saved to <ph name="GOOGLE_PASSWORD_MANAGER">$1<ex>Google Password Manager</ex></ph> for <ph name="EMAIL">$2<ex>user@gmail.com</ex></ph>.
       </message>
       <message name="IDS_PASSWORD_BUBBLES_FOOTER_SAVING_ON_DEVICE" desc="The footer text of the bubbles that offers users to save, update or manage stored passwords only locally in Chrome.">
-        Passwords are saved to <ph name="GOOGLE_PASSWORD_MANAGER">$1<ex>Google Password Manager</ex></ph> on this device
+        Passwords are saved to <ph name="GOOGLE_PASSWORD_MANAGER">$1<ex>Google Password Manager</ex></ph> on this device.
       </message>
       <message name="IDS_PASSWORD_GENERATION_CONFIRMATION_GOOGLE_PASSWORD_MANAGER" desc="A message that the browser shows after saving a password it has autogenerated for the user. This message appears in a bubble and contains a link to all the user's saved passwords. The link text is a separate string in the translation console and appears here as placeholder text.">
-          You can view and manage saved passwords in <ph name="GOOGLE_PASSWORD_MANAGER">$1<ex>Google Password Manager</ex></ph>
+          You can view and manage saved passwords in <ph name="GOOGLE_PASSWORD_MANAGER">$1<ex>Google Password Manager</ex></ph>.
       </message>
       <message name="IDS_PASSWORD_GENERATION_PROMPT_GOOGLE_PASSWORD_MANAGER" desc="Autofill dropdown text describing password generation.">
-          You won't need to remember this password. It will be saved to <ph name="GOOGLE_PASSWORD_MANAGER">$1<ex>Google Password Manager</ex></ph> for <ph name="EMAIL">$2<ex>user@gmail.com</ex></ph>
+          You won't need to remember this password. It will be saved to <ph name="GOOGLE_PASSWORD_MANAGER">$1<ex>Google Password Manager</ex></ph> for <ph name="EMAIL">$2<ex>user@gmail.com</ex></ph>.
       </message>
       <message name="IDS_PASSWORD_MANAGEMENT_BUBBLE_FOOTER_ACCOUNT_STORE_USERS" desc="The footer text of the managment bubble the lists saved password for this website. This is used only for account store users.">
-        Passwords are saved to <ph name="GOOGLE_PASSWORD_MANAGER">$1<ex>Google Password Manager</ex></ph>
+        Passwords are saved to <ph name="GOOGLE_PASSWORD_MANAGER">$1<ex>Google Password Manager</ex></ph>.
       </message>
       <message name="IDS_PASSWORD_MANAGER_GENERATED_PASSWORD_SAVED_MESSAGE_DESCRIPTION" desc="The description in the Google Password Manager's message that appears after saving a password that was autogenerated for the user.">
         You can view and manage saved passwords in Google Password Manager
@@ -7508,9 +7508,18 @@
         <message name="IDS_PASSWORD_MANAGER_SAVE_UNSYNCED_CREDENTIALS_BUTTON" desc="Button text for the 'save unsynced credentials' bubble's save option.">
           Save
         </message>
-        <message name="IDS_PASSWORD_MANAGER_SAVE_UNSYNCED_CREDENTIALS_BUTTON_GPM" desc="Button text for the 'save unsynced credentials' bubble's save option.">
-          Save to device
-        </message>
+
+        <if expr="not use_titlecase">
+          <message name="IDS_PASSWORD_MANAGER_SAVE_UNSYNCED_CREDENTIALS_BUTTON_GPM" desc="Button text for the 'save unsynced credentials' bubble's save option.">
+            Save to device
+          </message>
+        </if>
+        <if expr="use_titlecase">
+          <message name="IDS_PASSWORD_MANAGER_SAVE_UNSYNCED_CREDENTIALS_BUTTON_GPM" desc="In Title Case: Button text for the 'save unsynced credentials' bubble's save option.">
+            Save to Device
+          </message>
+        </if>
+
         <message name="IDS_PASSWORD_MANAGER_DISCARD_UNSYNCED_CREDENTIALS_BUTTON" desc="Button text for the 'save unsynced credentials' bubble's discard option.">
           No thanks
         </message>
diff --git a/chrome/app/generated_resources_grd/IDS_PASSWORD_BUBBLES_FOOTER_SAVING_ON_DEVICE.png.sha1 b/chrome/app/generated_resources_grd/IDS_PASSWORD_BUBBLES_FOOTER_SAVING_ON_DEVICE.png.sha1
index 2794fe7..b1a2ea5 100644
--- a/chrome/app/generated_resources_grd/IDS_PASSWORD_BUBBLES_FOOTER_SAVING_ON_DEVICE.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_PASSWORD_BUBBLES_FOOTER_SAVING_ON_DEVICE.png.sha1
@@ -1 +1 @@
-e8af0b83ad05a00087e62b42eb7eaf8d37248127
\ No newline at end of file
+448156506864091b87995fe3fa67a7475d4ba389
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PASSWORD_BUBBLES_FOOTER_SYNCED_TO_ACCOUNT.png.sha1 b/chrome/app/generated_resources_grd/IDS_PASSWORD_BUBBLES_FOOTER_SYNCED_TO_ACCOUNT.png.sha1
index 01ad2dd..372c70a 100644
--- a/chrome/app/generated_resources_grd/IDS_PASSWORD_BUBBLES_FOOTER_SYNCED_TO_ACCOUNT.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_PASSWORD_BUBBLES_FOOTER_SYNCED_TO_ACCOUNT.png.sha1
@@ -1 +1 @@
-d4b485ccc95eb838e3973bad9a631a373d20c027
\ No newline at end of file
+066e8ee50102956909156d6b1f484c72a7fb7cdc
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PASSWORD_GENERATION_CONFIRMATION_GOOGLE_PASSWORD_MANAGER.png.sha1 b/chrome/app/generated_resources_grd/IDS_PASSWORD_GENERATION_CONFIRMATION_GOOGLE_PASSWORD_MANAGER.png.sha1
index 3890df8..e7217d0 100644
--- a/chrome/app/generated_resources_grd/IDS_PASSWORD_GENERATION_CONFIRMATION_GOOGLE_PASSWORD_MANAGER.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_PASSWORD_GENERATION_CONFIRMATION_GOOGLE_PASSWORD_MANAGER.png.sha1
@@ -1 +1 @@
-4052d307bba7467dbb9cf88dc416964d900baa42
\ No newline at end of file
+c2420a3d714272e527a3cf10214c58334b5b1f10
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PASSWORD_GENERATION_PROMPT_GOOGLE_PASSWORD_MANAGER.png.sha1 b/chrome/app/generated_resources_grd/IDS_PASSWORD_GENERATION_PROMPT_GOOGLE_PASSWORD_MANAGER.png.sha1
index d22732eb..86f75a61 100644
--- a/chrome/app/generated_resources_grd/IDS_PASSWORD_GENERATION_PROMPT_GOOGLE_PASSWORD_MANAGER.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_PASSWORD_GENERATION_PROMPT_GOOGLE_PASSWORD_MANAGER.png.sha1
@@ -1 +1 @@
-b65598748919a01f660e20c86c7e493250dfab48
\ No newline at end of file
+4a652db5ffacb341ddb71ba2986aee7bcfe1a045
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGEMENT_BUBBLE_FOOTER_ACCOUNT_STORE_USERS.png.sha1 b/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGEMENT_BUBBLE_FOOTER_ACCOUNT_STORE_USERS.png.sha1
index 7284855..0886674 100644
--- a/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGEMENT_BUBBLE_FOOTER_ACCOUNT_STORE_USERS.png.sha1
+++ b/chrome/app/generated_resources_grd/IDS_PASSWORD_MANAGEMENT_BUBBLE_FOOTER_ACCOUNT_STORE_USERS.png.sha1
@@ -1 +1 @@
-7769ce5b517a11186bf906e18e23106502a13286
\ No newline at end of file
+7acb94a5d531db92d790e39ee21848be6a8e89ff
\ No newline at end of file
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/MainActivity.java b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/MainActivity.java
index c9eae16..3238393 100644
--- a/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/MainActivity.java
+++ b/chrome/browser/android/examples/custom_tabs_client/src/java/org/chromium/customtabsclient/MainActivity.java
@@ -29,6 +29,8 @@
 import android.widget.ArrayAdapter;
 import android.widget.Button;
 import android.widget.EditText;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.Spinner;
 import android.widget.TextView;
 
@@ -69,6 +71,8 @@
     private Button mLaunchPartialHeightCctButton;
     private MediaPlayer mMediaPlayer;
     private MaterialButtonToggleGroup mCloseButtonPositionToggle;
+    private TextView mToolbarCornerRadiusLabel;
+    private SeekBar mToolbarCornerRadiusSlider;
 
     /**
      * Once per second, asks the framework for the process importance, and logs any change.
@@ -127,6 +131,22 @@
         findViewById(R.id.register_twa_service).setOnClickListener(this);
         mCloseButtonPositionToggle = findViewById(R.id.close_button_position_toggle);
         mCloseButtonPositionToggle.check(R.id.start_button);
+        mToolbarCornerRadiusLabel = findViewById(R.id.corner_radius_slider_label);
+        mToolbarCornerRadiusSlider = findViewById(R.id.corner_radius_slider);
+        mToolbarCornerRadiusLabel.setText(
+                getString(R.string.dp_template, mToolbarCornerRadiusSlider.getProgress()));
+        mToolbarCornerRadiusSlider.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+            @Override
+            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                mToolbarCornerRadiusLabel.setText(getString(R.string.dp_template, progress));
+            }
+
+            @Override
+            public void onStartTrackingTouch(SeekBar seekBar) {}
+
+            @Override
+            public void onStopTrackingTouch(SeekBar seekBar) {}
+        });
 
         Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
         PackageManager pm = getPackageManager();
@@ -276,6 +296,12 @@
                     "androidx.browser.customtabs.extra.INITIAL_ACTIVITY_HEIGHT_IN_PIXEL", 500);
             customTabsIntent.intent.putExtra(
                     "androidx.browser.customtabs.extra.CLOSE_BUTTON_POSITION", closeButtonPosition);
+            int toolbarCornerRadiusDp = mToolbarCornerRadiusSlider.getProgress();
+            int toolbarCornerRadiusPx =
+                    Math.round(toolbarCornerRadiusDp * getResources().getDisplayMetrics().density);
+            customTabsIntent.intent.putExtra(
+                    "androidx.browser.customtabs.extra.TOOLBAR_CORNER_RADIUS_IN_PIXEL",
+                    toolbarCornerRadiusPx);
             customTabsIntent.launchUrl(this, Uri.parse(url));
         }
     }
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/layout/main.xml b/chrome/browser/android/examples/custom_tabs_client/src/res/layout/main.xml
index 0c50d65e..c9c57d0 100644
--- a/chrome/browser/android/examples/custom_tabs_client/src/res/layout/main.xml
+++ b/chrome/browser/android/examples/custom_tabs_client/src/res/layout/main.xml
@@ -67,7 +67,9 @@
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="horizontal">
+            android:orientation="horizontal"
+            android:layout_marginStart="3dp"
+            android:layout_marginBottom="16dp">
             <TextView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
@@ -77,9 +79,11 @@
                 style="?attr/textAppearanceLabelLarge" />
             <com.google.android.material.button.MaterialButtonToggleGroup
                 android:id="@+id/close_button_position_toggle"
-                android:layout_width="wrap_content"
+                android:layout_width="0dp"
                 android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical|end"
+                android:layout_gravity="center_vertical"
+                android:layout_weight="1"
+                android:gravity="center_horizontal"
                 app:singleSelection="true"
                 app:selectionRequired="true">
                 <Button
@@ -97,6 +101,39 @@
             </com.google.android.material.button.MaterialButtonToggleGroup>
         </LinearLayout>
 
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:gravity="center_vertical"
+            android:layout_marginStart="3dp"
+            android:layout_marginBottom="16dp">
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/toolbar_corner_radius_text"
+                android:layout_marginEnd="8dp"
+                android:maxWidth="160sp"
+                style="?attr/textAppearanceLabelLarge" />
+            <TextView
+                android:id="@+id/corner_radius_slider_label"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:gravity="center_vertical|end"
+                android:minWidth="40sp"
+                android:labelFor="@+id/corner_radius_slider"
+                android:contentDescription="@string/toolbar_corner_radius_slider_label_desc"
+                style="?attr/textAppearanceLabelLarge" />
+            <SeekBar
+                android:id="@+id/corner_radius_slider"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:layout_weight="1"
+                android:progress="16"
+                android:max="72"/>
+        </LinearLayout>
+
         <Space
             android:layout_width="match_parent"
             android:layout_height="5dp" />
diff --git a/chrome/browser/android/examples/custom_tabs_client/src/res/values/strings.xml b/chrome/browser/android/examples/custom_tabs_client/src/res/values/strings.xml
index defa6c8..16d1db00 100644
--- a/chrome/browser/android/examples/custom_tabs_client/src/res/values/strings.xml
+++ b/chrome/browser/android/examples/custom_tabs_client/src/res/values/strings.xml
@@ -20,6 +20,9 @@
     <string name="close_button_position_text">Close Button Position</string>
     <string name="close_button_start_text">Default/Start</string>
     <string name="close_button_end_text">End</string>
+    <string name="toolbar_corner_radius_text">Partial Height CCT Toolbar Corner Radius</string>
+    <string name="toolbar_corner_radius_slider_label_desc">Toolbar corner radius</string>
+    <string name="dp_template">%ddp</string>
     <string name="warmup_button_text">Warmup Chrome</string>
     <string name="may_launch_button_text">May Launch URL</string>
     <string name="launch_button_text">Launch URL in a Chrome Custom Tab</string>
diff --git a/chrome/browser/ash/android_sms/android_sms_service_factory.cc b/chrome/browser/ash/android_sms/android_sms_service_factory.cc
index 377ccbb..d1aceed0 100644
--- a/chrome/browser/ash/android_sms/android_sms_service_factory.cc
+++ b/chrome/browser/ash/android_sms/android_sms_service_factory.cc
@@ -4,8 +4,10 @@
 
 #include "chrome/browser/ash/android_sms/android_sms_service_factory.h"
 
+#include "ash/constants/ash_features.h"
 #include "ash/services/multidevice_setup/public/cpp/prefs.h"
 #include "ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
+#include "base/feature_list.h"
 #include "base/no_destructor.h"
 #include "chrome/browser/ash/multidevice_setup/multidevice_setup_client_factory.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -25,6 +27,11 @@
 namespace {
 
 bool ShouldStartAndroidSmsService(Profile* profile) {
+  if (base::FeatureList::IsEnabled(
+          features::kDisableMessagesCrossDeviceIntegration)) {
+    return false;
+  }
+
   const bool multidevice_feature_allowed = multidevice_setup::IsFeatureAllowed(
       multidevice_setup::mojom::Feature::kMessages, profile->GetPrefs());
 
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn
index 151585fd..7826a7a 100644
--- a/chrome/browser/ash/crosapi/BUILD.gn
+++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -344,6 +344,7 @@
     ":crosapi",
     ":test_support",
     "//ash",
+    "//ash/components/arc:arc_test_support",
     "//ash/components/cryptohome",
     "//base",
     "//base/test:test_config",
diff --git a/chrome/browser/ash/crosapi/browser_util_unittest.cc b/chrome/browser/ash/crosapi/browser_util_unittest.cc
index 9cf7533..defae9c 100644
--- a/chrome/browser/ash/crosapi/browser_util_unittest.cc
+++ b/chrome/browser/ash/crosapi/browser_util_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ash/crosapi/browser_util.h"
 
+#include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
 #include "base/command_line.h"
@@ -14,11 +15,16 @@
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/values.h"
+#include "chrome/browser/ash/crosapi/crosapi_util.h"
+#include "chrome/browser/ash/crosapi/environment_provider.h"
+#include "chrome/browser/ash/crosapi/idle_service_ash.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/policy/profile_policy_connector.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/crosapi/mojom/crosapi.mojom.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/policy_constants.h"
 #include "components/user_manager/scoped_user_manager.h"
@@ -797,4 +803,40 @@
   EXPECT_FALSE(browser_util::IsAshWebBrowserEnabled());
 }
 
+TEST_F(BrowserUtilTest, IsArcAvailable) {
+  arc::SetArcAvailableCommandLineForTesting(
+      base::CommandLine::ForCurrentProcess());
+  IdleServiceAsh::DisableForTesting();
+  ScopedTestingLocalState local_state(TestingBrowserProcess::GetGlobal());
+  AddRegularUser("user@google.com");
+
+  EnvironmentProvider environment_provider;
+  mojom::BrowserInitParamsPtr browser_init_params =
+      browser_util::GetBrowserInitParams(
+          &environment_provider,
+          browser_util::InitialBrowserAction(
+              crosapi::mojom::InitialBrowserAction::kDoNotOpenWindow),
+          /*is_keep_alive_enabled=*/false);
+  EXPECT_TRUE(browser_init_params->device_properties->is_arc_available);
+  EXPECT_FALSE(browser_init_params->device_properties->is_tablet_form_factor);
+}
+
+TEST_F(BrowserUtilTest, IsTabletFormFactor) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      ash::switches::kEnableTabletFormFactor);
+  IdleServiceAsh::DisableForTesting();
+  ScopedTestingLocalState local_state(TestingBrowserProcess::GetGlobal());
+  AddRegularUser("user@google.com");
+
+  EnvironmentProvider environment_provider;
+  mojom::BrowserInitParamsPtr browser_init_params =
+      browser_util::GetBrowserInitParams(
+          &environment_provider,
+          browser_util::InitialBrowserAction(
+              crosapi::mojom::InitialBrowserAction::kDoNotOpenWindow),
+          /*is_keep_alive_enabled=*/false);
+  EXPECT_FALSE(browser_init_params->device_properties->is_arc_available);
+  EXPECT_TRUE(browser_init_params->device_properties->is_tablet_form_factor);
+}
+
 }  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/crosapi_util.cc b/chrome/browser/ash/crosapi/crosapi_util.cc
index 8b54ade5..5d3fd871 100644
--- a/chrome/browser/ash/crosapi/crosapi_util.cc
+++ b/chrome/browser/ash/crosapi/crosapi_util.cc
@@ -6,6 +6,7 @@
 
 #include <sys/mman.h>
 
+#include "ash/components/arc/arc_util.h"
 #include "ash/components/settings/cros_settings_provider.h"
 #include "ash/components/tpm/install_attributes.h"
 #include "ash/constants/ash_features.h"
@@ -162,6 +163,8 @@
     }
   }
 
+  result->is_arc_available = arc::IsArcAvailable();
+  result->is_tablet_form_factor = ash::switches::IsTabletFormFactor();
   return result;
 }
 
diff --git a/chrome/browser/ash/cryptauth/client_app_metadata_provider_service.cc b/chrome/browser/ash/cryptauth/client_app_metadata_provider_service.cc
index 7df8d86..38fc8d9 100644
--- a/chrome/browser/ash/cryptauth/client_app_metadata_provider_service.cc
+++ b/chrome/browser/ash/cryptauth/client_app_metadata_provider_service.cc
@@ -46,17 +46,21 @@
       feature_metadata([] {
         cryptauthv2::BetterTogetherFeatureMetadata inner_metadata;
 
-        // Smart Lock, MultiDevice Setup and Messages are supported on all
-        // Chromebooks.
+        // Smart Lock and MultiDevice Setup are supported on all Chromebooks.
         inner_metadata.add_supported_features(
             cryptauthv2::
                 BetterTogetherFeatureMetadata_FeatureName_EASY_UNLOCK_CLIENT);
         inner_metadata.add_supported_features(
             cryptauthv2::
                 BetterTogetherFeatureMetadata_FeatureName_BETTER_TOGETHER_CLIENT);
-        inner_metadata.add_supported_features(
-            cryptauthv2::
-                BetterTogetherFeatureMetadata_FeatureName_SMS_CONNECT_CLIENT);
+
+        // Disable Messages integration when pre-installing app on all devices.
+        if (!base::FeatureList::IsEnabled(
+                features::kDisableMessagesCrossDeviceIntegration)) {
+          inner_metadata.add_supported_features(
+              cryptauthv2::
+                  BetterTogetherFeatureMetadata_FeatureName_SMS_CONNECT_CLIENT);
+        }
 
         // Instant Tethering is only supported if the associated flag enabled.
         if (base::FeatureList::IsEnabled(features::kInstantTethering)) {
diff --git a/chrome/browser/ash/cryptauth/gcm_device_info_provider_impl.cc b/chrome/browser/ash/cryptauth/gcm_device_info_provider_impl.cc
index 3dc9b55..a8386b0 100644
--- a/chrome/browser/ash/cryptauth/gcm_device_info_provider_impl.cc
+++ b/chrome/browser/ash/cryptauth/gcm_device_info_provider_impl.cc
@@ -74,14 +74,18 @@
     // phones/tablets, but it must be set due to server API verification.
     gcm_device_info.set_device_display_diagonal_mils(0);
 
-    // Smart Lock, MultiDevice Setup and Messages are supported on all
-    // Chromebooks.
+    // Smart Lock and MultiDevice Setup are supported on all Chromebooks.
     gcm_device_info.add_supported_software_features(
         cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT);
     gcm_device_info.add_supported_software_features(
         cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT);
-    gcm_device_info.add_supported_software_features(
-        cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT);
+
+    // Disable Messages integration when pre-installing app on all devices.
+    if (!base::FeatureList::IsEnabled(
+            features::kDisableMessagesCrossDeviceIntegration)) {
+      gcm_device_info.add_supported_software_features(
+          cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT);
+    }
 
     // Instant Tethering is only supported if the associated flag is enabled.
     if (base::FeatureList::IsEnabled(features::kInstantTethering)) {
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_factory.cc b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_factory.cc
index dae5333..872b55ea 100644
--- a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_factory.cc
+++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_factory.cc
@@ -96,7 +96,8 @@
         profile,
         secure_channel::SecureChannelClientProvider::GetInstance()
             ->GetClient());
-  } else if (!ProfileHelper::IsRegularProfile(profile)) {
+  } else if (!ProfileHelper::IsRegularProfile(profile) ||
+             !ProfileHelper::IsPrimaryProfile(profile)) {
     return nullptr;
   }
 
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc
index 37a9db83..8557b0b 100644
--- a/chrome/browser/browser_features.cc
+++ b/chrome/browser/browser_features.cc
@@ -120,9 +120,10 @@
 // Implementation bug: https://crbug.com/1253379
 // I2S: https://groups.google.com/a/chromium.org/g/blink-dev/c/-t-f7I6VvOI
 //
-// To be enabled in M103
+// Enabled in M103. Flag to be removed in M106
 const base::Feature kSandboxExternalProtocolBlocked{
-    "SandboxExternalProtocolBlocked", base::FEATURE_DISABLED_BY_DEFAULT};
+    "SandboxExternalProtocolBlocked", base::FEATURE_ENABLED_BY_DEFAULT};
+// Enabled in M100. Flag to be removed in M106
 const base::Feature kSandboxExternalProtocolBlockedWarning{
     "SandboxExternalProtocolBlockedWarning", base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/chrome_back_forward_cache_browsertest.cc b/chrome/browser/chrome_back_forward_cache_browsertest.cc
index 780f8c3..d9cff155 100644
--- a/chrome/browser/chrome_back_forward_cache_browsertest.cc
+++ b/chrome/browser/chrome_back_forward_cache_browsertest.cc
@@ -253,10 +253,12 @@
             content::RenderFrameHost::LifecycleState::kInBackForwardCache);
   base::MockOnceCallback<void(blink::mojom::PermissionStatus)> callback;
   EXPECT_CALL(callback, Run(blink::mojom::PermissionStatus::ASK));
-  // PermissionManagerFactory::GetForProfile(browser()->profile())
-  browser()->profile()->GetPermissionController()->RequestPermission(
-      blink::PermissionType::GEOLOCATION, rfh_a.get(), url_a,
-      /* user_gesture = */ true, callback.Get());
+  browser()
+      ->profile()
+      ->GetPermissionController()
+      ->RequestPermissionFromCurrentDocument(
+          blink::PermissionType::GEOLOCATION, rfh_a.get(),
+          /* user_gesture = */ true, callback.Get());
 
   // Ensure |rfh_a| is evicted from the cache because it is not allowed to
   // service the GEOLOCATION permission request.
diff --git a/chrome/browser/device_api/managed_configuration_api_browsertest.cc b/chrome/browser/device_api/managed_configuration_api_browsertest.cc
index 778d268a..b4e9b52 100644
--- a/chrome/browser/device_api/managed_configuration_api_browsertest.cc
+++ b/chrome/browser/device_api/managed_configuration_api_browsertest.cc
@@ -114,16 +114,15 @@
 
   void SetConfiguration(const std::string& conf_url,
                         const std::string& conf_hash) {
-    auto trusted_apps = std::make_unique<base::ListValue>();
-    auto entry = std::make_unique<base::DictionaryValue>();
-    entry->SetStringKey(ManagedConfigurationAPI::kOriginKey, kOrigin);
-    entry->SetStringKey(ManagedConfigurationAPI::kManagedConfigurationUrlKey,
-                        embedded_test_server()->GetURL(conf_url).spec());
-    entry->SetStringKey(ManagedConfigurationAPI::kManagedConfigurationHashKey,
-                        conf_hash);
-    trusted_apps->Append(std::move(entry));
+    base::Value::List trusted_apps;
+    base::Value::Dict entry;
+    entry.Set(ManagedConfigurationAPI::kOriginKey, kOrigin);
+    entry.Set(ManagedConfigurationAPI::kManagedConfigurationUrlKey,
+              embedded_test_server()->GetURL(conf_url).spec());
+    entry.Set(ManagedConfigurationAPI::kManagedConfigurationHashKey, conf_hash);
+    trusted_apps.Append(std::move(entry));
     profile()->GetPrefs()->Set(prefs::kManagedConfigurationPerOrigin,
-                               *trusted_apps);
+                               base::Value(std::move(trusted_apps)));
   }
 
   void ClearConfiguration() {
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index d4786ba..45e96c3 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -82,6 +82,7 @@
 const base::Feature* const kFeaturesExposedToJava[] = {
     &autofill::features::kAutofillAddressProfileSavePromptNicknameSupport,
     &autofill::features::kAutofillCreditCardAuthentication,
+    &autofill::features::kAutofillEnableRankingFormula,
     &autofill::features::kAutofillEnableManualFallbackForVirtualCards,
     &autofill::features::kAutofillKeyboardAccessory,
     &autofill::features::kAutofillManualFallbackAndroid,
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index 961e964..83da67e 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -206,6 +206,7 @@
             "AutofillAllowNonHttpActivation";
     public static final String AUTOFILL_CREDIT_CARD_AUTHENTICATION =
             "AutofillCreditCardAuthentication";
+    public static final String AUTOFILL_ENABLE_RANKING_FORMULA = "AutofillEnableRankingFormula";
     public static final String AUTOFILL_ENABLE_MANUAL_FALLBACK_FOR_VIRTUAL_CARDS =
             "AutofillEnableManualFallbackForVirtualCards";
     public static final String AUTOFILL_ENABLE_SUPPORT_FOR_HONORIFIC_PREFIXES =
@@ -216,6 +217,8 @@
             "AutofillEnableSupportForMoreStructureInNames";
     public static final String AUTOFILL_ENABLE_UPDATE_VIRTUAL_CARD_ENROLLMENT =
             "AutofillEnableUpdateVirtualCardEnrollment";
+    public static final String AUTOFILL_RANKING_FORMULA_USAGE_HALF_LIFE =
+            "AutofillRankingFormulaUsageHalfLife";
     public static final String ANDROID_SEARCH_ENGINE_CHOICE_NOTIFICATION =
             "AndroidSearchEngineChoiceNotification";
     public static final String ANONYMOUS_UPDATE_CHECKS = "AnonymousUpdateChecks";
diff --git a/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc
index 100e007..003e517 100644
--- a/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc
+++ b/chrome/browser/geolocation/geolocation_permission_context_delegate_unittest.cc
@@ -15,6 +15,7 @@
 #include "components/permissions/permission_result.h"
 #include "components/permissions/test/mock_permission_prompt_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/permissions/permission_utils.h"
 
 #if BUILDFLAG(IS_ANDROID)
 #include "chrome/browser/android/search_permissions/search_permissions_service.h"
@@ -66,13 +67,21 @@
   }
 
   void RequestPermissionFromCurrentDocument(
-      ContentSettingsType permission,
+      blink::PermissionType permission,
       content::RenderFrameHost* render_frame_host,
       bool user_gesture,
-      base::OnceCallback<void(ContentSetting)> callback) {
+      base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) {
     PermissionManagerFactory::GetForProfile(profile())
-        ->RequestPermissionFromCurrentDocument(
-            permission, render_frame_host, user_gesture, std::move(callback));
+        ->RequestPermissionsFromCurrentDocument(
+            {permission}, render_frame_host, user_gesture,
+            base::BindOnce(
+                [](base::OnceCallback<void(blink::mojom::PermissionStatus)>
+                       callback,
+                   const std::vector<blink::mojom::PermissionStatus>& state) {
+                  DCHECK_EQ(state.size(), 1U);
+                  std::move(callback).Run(state[0]);
+                },
+                std::move(callback)));
   }
 
   permissions::PermissionResult GetPermissionStatusForDisplayOnSettingsUI(
@@ -94,10 +103,10 @@
 
   base::RunLoop run_loop;
   RequestPermissionFromCurrentDocument(
-      ContentSettingsType::GEOLOCATION, main_rfh(), true,
+      blink::PermissionType::GEOLOCATION, main_rfh(), true,
       base::BindOnce(
-          [](base::RunLoop* run_loop, ContentSetting content_setting) {
-            EXPECT_EQ(content_setting, CONTENT_SETTING_ALLOW);
+          [](base::RunLoop* run_loop, blink::mojom::PermissionStatus status) {
+            EXPECT_EQ(status, blink::mojom::PermissionStatus::GRANTED);
             run_loop->Quit();
           },
           &run_loop));
diff --git a/chrome/browser/incognito/BUILD.gn b/chrome/browser/incognito/BUILD.gn
index 9b64548..3cef0d6 100644
--- a/chrome/browser/incognito/BUILD.gn
+++ b/chrome/browser/incognito/BUILD.gn
@@ -20,6 +20,7 @@
     "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthProperties.java",
     "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthSettingSwitchPreference.java",
     "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthSettingUtils.java",
+    "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthTabSwitcherDelegate.java",
     "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthViewBinder.java",
   ]
   deps = [
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthController.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthController.java
index 0dae24e2..6812f91 100644
--- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthController.java
+++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthController.java
@@ -154,6 +154,7 @@
         mTabModelSelector.removeObserver(mTabModelSelectorObserver);
         mProfileObservableSupplier.removeObserver(mProfileSupplierCallback);
         mLayoutStateProviderCallbackController.destroy();
+        mIncognitoReauthCoordinatorFactory.destroy();
         hideDialogIfShowing(DialogDismissalCause.ACTIVITY_DESTROYED);
     }
 
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinator.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinator.java
index e76dbd8..05ed626 100644
--- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinator.java
+++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinator.java
@@ -25,15 +25,21 @@
 /**
  * The coordinator which is responsible for showing the Incognito re-authentication page.
  *
+ * This is created and removed each time the incognito re-auth screen is shown/hidden
+ * respectively.
+ *
  * TODO(crbug.com/1227656): Add support to disable/enable certain UI elements in the Toolbar when
  * the re-auth dialog is shown/hidden in the Incognito tab switcher.
  */
 class IncognitoReauthCoordinator {
     private final @NonNull Context mContext;
     private final @NonNull ModalDialogManager mModalDialogManager;
+    // This can be null if the {link TabSwitcherCustomViewManager} is not yet created.
+    private final @Nullable IncognitoReauthTabSwitcherDelegate mIncognitoReauthTabSwitcherDelegate;
     private final boolean mShowFullScreen;
-    private final @Nullable IncognitoReauthMenuDelegate mIncognitoReauthMenuDelegate;
 
+    // Non-null for full screen re-auth dialog.
+    private final @Nullable IncognitoReauthMenuDelegate mIncognitoReauthMenuDelegate;
     private final IncognitoReauthMediator mIncognitoReauthMediator;
 
     private View mIncognitoReauthView;
@@ -53,6 +59,8 @@
      *         to initiate re-authentication.
      * @param settingsLauncher A {@link SettingsLauncher} that allows to fire {@link
      *         SettingsActivity}.
+     * @param incognitoReauthTabSwitcherDelegate A {@link IncognitoReauthTabSwitcherDelegate} that
+     *         allows to communicate with tab switcher to show the re-auth screen.
      * @param showFullScreen Whether to show a fullscreen / tab based re-auth dialog.
      */
     public IncognitoReauthCoordinator(@NonNull Context context,
@@ -60,9 +68,12 @@
             @NonNull ModalDialogManager modalDialogManager,
             @NonNull IncognitoReauthManager.IncognitoReauthCallback incognitoReauthCallback,
             @NonNull IncognitoReauthManager incognitoReauthManager,
-            @NonNull SettingsLauncher settingsLauncher, boolean showFullScreen) {
+            @NonNull SettingsLauncher settingsLauncher,
+            @Nullable IncognitoReauthTabSwitcherDelegate incognitoReauthTabSwitcherDelegate,
+            boolean showFullScreen) {
         mContext = context;
         mModalDialogManager = modalDialogManager;
+        mIncognitoReauthTabSwitcherDelegate = incognitoReauthTabSwitcherDelegate;
         mShowFullScreen = showFullScreen;
         mIncognitoReauthMediator = new IncognitoReauthMediator(
                 tabModelSelector, incognitoReauthCallback, incognitoReauthManager);
@@ -86,14 +97,31 @@
                 mIncognitoReauthMediator::onSeeOtherTabsButtonClicked, mShowFullScreen, delegate);
         mModelChangeProcessor = PropertyModelChangeProcessor.create(
                 mPropertyModel, mIncognitoReauthView, IncognitoReauthViewBinder::bind);
-        mIncognitoReauthDialog =
-                new IncognitoReauthDialog(mModalDialogManager, mIncognitoReauthView);
-        mIncognitoReauthDialog.showIncognitoReauthDialog(mShowFullScreen);
+
+        if (mShowFullScreen) {
+            mIncognitoReauthDialog =
+                    new IncognitoReauthDialog(mModalDialogManager, mIncognitoReauthView);
+            mIncognitoReauthDialog.showIncognitoReauthDialog(mShowFullScreen);
+        } else {
+            assert mIncognitoReauthTabSwitcherDelegate
+                    != null : "delegate to TabSwitcher can't be null.";
+            boolean success = mIncognitoReauthTabSwitcherDelegate.addReauthScreenInTabSwitcher(
+                    mIncognitoReauthView);
+            assert success : "Unable to signal showing the re-auth screen to tab switcher.";
+        }
     }
 
     void hideDialogAndDestroy(@DialogDismissalCause int dismissalCause) {
-        assert mIncognitoReauthDialog != null : "Incognito re-auth dialog doesn't exists.";
-        mIncognitoReauthDialog.dismissIncognitoReauthDialog(dismissalCause);
+        if (mShowFullScreen) {
+            assert mIncognitoReauthDialog != null : "Incognito re-auth dialog doesn't exists.";
+            mIncognitoReauthDialog.dismissIncognitoReauthDialog(dismissalCause);
+        } else {
+            assert mIncognitoReauthTabSwitcherDelegate
+                    != null : "delegate to TabSwitcher can't be null.";
+            boolean success =
+                    mIncognitoReauthTabSwitcherDelegate.removeReauthScreenFromTabSwitcher();
+            assert success : "Unable to signal removing the re-auth screen from tab switcher.";
+        }
         destroy();
     }
 }
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinatorFactory.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinatorFactory.java
index 52ab40ab..15a83f6f 100644
--- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinatorFactory.java
+++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinatorFactory.java
@@ -7,7 +7,10 @@
 import android.content.Context;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
+import org.chromium.base.CallbackController;
+import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.ui.modaldialog.ModalDialogManager;
@@ -22,6 +25,11 @@
     private final @NonNull IncognitoReauthManager mIncognitoReauthManager;
     private final @NonNull SettingsLauncher mSettingsLauncher;
 
+    // A callback controller for initializing the |mIncognitoReauthTabSwitcherDelegate| which is
+    // invoked once the {@link TabSwitcherCustomViewManager} is initiated and created.
+    private final CallbackController mTabSwitcherDelegateController = new CallbackController();
+    private @Nullable IncognitoReauthTabSwitcherDelegate mIncognitoReauthTabSwitcherDelegate;
+
     /**
      * @param context The {@link Context} to use for inflating the Incognito re-auth view.
      * @param tabModelSelector The {@link TabModelSelector} which will be passed to the mediator in
@@ -30,16 +38,30 @@
      *         containing the Incognito re-auth view.
      * @param  settingsLauncher A {@link SettingsLauncher} that allows to launch {@link
      *         SettingsActivity} from 3 dots menu.
+     * @param incognitoReauthTabSwitcherDelegateSupplier A {@link OneshotSupplier
+     *         <IncognitoReauthTabSwitcherDelegate>} that allows to communicate with tab switcher to
+     *         show the re-auth screen.
      */
     public IncognitoReauthCoordinatorFactory(@NonNull Context context,
             @NonNull TabModelSelector tabModelSelector,
             @NonNull ModalDialogManager modalDialogManager,
-            @NonNull SettingsLauncher settingsLauncher) {
+            @NonNull SettingsLauncher settingsLauncher,
+            @NonNull OneshotSupplier<IncognitoReauthTabSwitcherDelegate>
+                    incognitoReauthTabSwitcherDelegateSupplier) {
         mContext = context;
         mTabModelSelector = tabModelSelector;
         mModalDialogManager = modalDialogManager;
         mIncognitoReauthManager = new IncognitoReauthManager();
         mSettingsLauncher = settingsLauncher;
+        incognitoReauthTabSwitcherDelegateSupplier.onAvailable(
+                mTabSwitcherDelegateController.makeCancelable(delegate -> {
+                    assert delegate != null;
+                    mIncognitoReauthTabSwitcherDelegate = delegate;
+                }));
+    }
+
+    void destroy() {
+        mTabSwitcherDelegateController.destroy();
     }
 
     IncognitoReauthCoordinator createIncognitoReauthCoordinator(
@@ -47,6 +69,6 @@
             boolean showFullScreen) {
         return new IncognitoReauthCoordinator(mContext, mTabModelSelector, mModalDialogManager,
                 incognitoReauthCallback, mIncognitoReauthManager, mSettingsLauncher,
-                showFullScreen);
+                mIncognitoReauthTabSwitcherDelegate, showFullScreen);
     }
 }
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthTabSwitcherDelegate.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthTabSwitcherDelegate.java
new file mode 100644
index 0000000..d4c50bea
--- /dev/null
+++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthTabSwitcherDelegate.java
@@ -0,0 +1,34 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.incognito.reauth;
+
+import android.view.View;
+
+import androidx.annotation.NonNull;
+
+/**
+ * An interface to establish communication with {@link TabSwitcherCustomViewManager} to support
+ * showing re-auth screen in tab switcher UI.
+ *
+ * TODO(crbug.com/1324211, crbug.com/1227656) : Remove this interface once tab_ui is modularized.
+ */
+public interface IncognitoReauthTabSwitcherDelegate {
+    /**
+     * A method to supply the incognito re-auth view to tab switcher.
+     *
+     * @param customView A {@link View} that needs to be added to the tab switcher content area.
+     * @return True, if the signal was relayed successfully to {@link TabSwitcherCustomViewManager},
+     *         false otherwise.
+     */
+    boolean addReauthScreenInTabSwitcher(@NonNull View customView);
+
+    /**
+     * A method to remove the incognito re-auth view from tab switcher.
+     *
+     * @return True, if the signal was relayed successfully to {@link TabSwitcherCustomViewManager},
+     *         false otherwise.
+     */
+    boolean removeReauthScreenFromTabSwitcher();
+}
diff --git a/chrome/browser/media/router/discovery/access_code/access_code_cast_pref_updater.cc b/chrome/browser/media/router/discovery/access_code/access_code_cast_pref_updater.cc
index dbd2f51..bb7c253 100644
--- a/chrome/browser/media/router/discovery/access_code/access_code_cast_pref_updater.cc
+++ b/chrome/browser/media/router/discovery/access_code/access_code_cast_pref_updater.cc
@@ -45,6 +45,7 @@
   DCHECK(devices_pref) << "The " << prefs::kAccessCodeCastDevices
                        << " pref does not exist.";
 
+  // TODO(b/231748126): Add IP based-deduping for storing Access Code Cast Sinks
   devices_pref->SetDictionary(
       sink.id(), base::DictionaryValue::From(base::Value::ToUniquePtrValue(
                      CreateValueDictFromMediaSinkInternal(sink))));
diff --git a/chrome/browser/media_galleries/media_galleries_test_util.cc b/chrome/browser/media_galleries/media_galleries_test_util.cc
index ac3b77d..d3ceadc 100644
--- a/chrome/browser/media_galleries/media_galleries_test_util.cc
+++ b/chrome/browser/media_galleries/media_galleries_test_util.cc
@@ -53,16 +53,16 @@
   manifest->Set(extensions::manifest_keys::kPlatformAppBackgroundScripts,
                 std::move(background_script_list));
 
-  auto permission_detail_list = std::make_unique<base::ListValue>();
-  for (size_t i = 0; i < media_galleries_permissions.size(); i++)
-    permission_detail_list->Append(media_galleries_permissions[i]);
-  auto media_galleries_permission = std::make_unique<base::DictionaryValue>();
-  media_galleries_permission->Set("mediaGalleries",
-                                  std::move(permission_detail_list));
-  auto permission_list = std::make_unique<base::ListValue>();
-  permission_list->Append(std::move(media_galleries_permission));
-  manifest->Set(extensions::manifest_keys::kPermissions,
-                std::move(permission_list));
+  base::Value::List permission_detail_list;
+  for (const auto& permission : media_galleries_permissions)
+    permission_detail_list.Append(permission);
+  base::Value::Dict media_galleries_permission;
+  media_galleries_permission.Set("mediaGalleries",
+                                 std::move(permission_detail_list));
+  base::Value::List permission_list;
+  permission_list.Append(std::move(media_galleries_permission));
+  manifest->GetDict().Set(extensions::manifest_keys::kPermissions,
+                          std::move(permission_list));
 
   extensions::ExtensionPrefs* extension_prefs =
       extensions::ExtensionPrefs::Get(profile);
diff --git a/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.cc b/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.cc
index 01560f87..46f5d579 100644
--- a/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.cc
+++ b/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
 #include "chrome/browser/password_manager/android/password_manager_lifecycle_helper_impl.h"
 #include "chrome/browser/password_manager/android/password_settings_updater_android_bridge.h"
 #include "chrome/browser/password_manager/android/password_settings_updater_android_bridge_impl.h"
@@ -25,6 +26,10 @@
 
 namespace {
 
+constexpr PasswordManagerSetting kAllPasswordSettings[] = {
+    PasswordManagerSetting::kOfferToSavePasswords,
+    PasswordManagerSetting::kAutoSignIn};
+
 // Returns the preference in which a setting value coming from Google Mobile
 // Services should be stored.
 const PrefService::Preference* GetGMSPrefFromSetting(
@@ -71,14 +76,15 @@
   DCHECK(pref_service_);
   DCHECK(sync_service_);
   DCHECK(password_manager::features::UsesUnifiedPasswordManagerUi());
-  if (PasswordSettingsUpdaterAndroidBridge::CanCreateAccessor()) {
-    bridge_ = PasswordSettingsUpdaterAndroidBridge::Create();
-    bridge_->SetConsumer(weak_ptr_factory_.GetWeakPtr());
-    lifecycle_helper_ = std::make_unique<PasswordManagerLifecycleHelperImpl>();
-    lifecycle_helper_->RegisterObserver(base::BindRepeating(
-        &PasswordManagerSettingsServiceAndroidImpl::OnChromeForegrounded,
-        weak_ptr_factory_.GetWeakPtr()));
-  }
+  if (!PasswordSettingsUpdaterAndroidBridge::CanCreateAccessor())
+    return;
+  MigratePrefsIfNeeded();
+  bridge_ = PasswordSettingsUpdaterAndroidBridge::Create();
+  bridge_->SetConsumer(weak_ptr_factory_.GetWeakPtr());
+  lifecycle_helper_ = std::make_unique<PasswordManagerLifecycleHelperImpl>();
+  lifecycle_helper_->RegisterObserver(base::BindRepeating(
+      &PasswordManagerSettingsServiceAndroidImpl::OnChromeForegrounded,
+      weak_ptr_factory_.GetWeakPtr()));
 }
 
 // Constructor for tests
@@ -95,12 +101,13 @@
       lifecycle_helper_(std::move(lifecycle_helper)) {
   DCHECK(pref_service_);
   DCHECK(sync_service_);
-  if (bridge_) {
-    bridge_->SetConsumer(weak_ptr_factory_.GetWeakPtr());
-    lifecycle_helper_->RegisterObserver(base::BindRepeating(
-        &PasswordManagerSettingsServiceAndroidImpl::OnChromeForegrounded,
-        weak_ptr_factory_.GetWeakPtr()));
-  }
+  if (!bridge_)
+    return;
+  MigratePrefsIfNeeded();
+  bridge_->SetConsumer(weak_ptr_factory_.GetWeakPtr());
+  lifecycle_helper_->RegisterObserver(base::BindRepeating(
+      &PasswordManagerSettingsServiceAndroidImpl::OnChromeForegrounded,
+      weak_ptr_factory_.GetWeakPtr()));
 }
 
 PasswordManagerSettingsServiceAndroidImpl::
@@ -170,7 +177,7 @@
 
   // If both GMS and Chrome have default values for the setting, then no update
   // is needed.
-  if (pref->IsDefaultValue())
+  if (!pref_service_->GetUserPrefValue(pref->name()))
     return;
 
   // If Chrome has an explicitly set value, GMS needs to know about it.
@@ -181,3 +188,36 @@
           sync_service_->GetAccountInfo().email),
       setting, pref->GetValue()->GetBool());
 }
+
+void PasswordManagerSettingsServiceAndroidImpl::MigratePrefsIfNeeded() {
+  if (pref_service_->GetBoolean(
+          password_manager::prefs::kSettingsMigratedToUPM))
+    return;
+
+  base::UmaHistogramBoolean("PasswordManager.MigratedSettingsUPMAndroid", true);
+  pref_service_->SetBoolean(password_manager::prefs::kSettingsMigratedToUPM,
+                            true);
+  // No need to copy the values until sync turns on. When sync turns on, this
+  // will be handled as part of the sync state change rather than migration.
+  if (!IsPasswordSyncEnabled(sync_service_))
+    return;
+
+  for (PasswordManagerSetting setting : kAllPasswordSettings) {
+    const PrefService::Preference* regular_pref =
+        GetRegularPrefFromSetting(pref_service_, setting);
+
+    if (!pref_service_->GetUserPrefValue(regular_pref->name())) {
+      continue;
+    }
+
+    const PrefService::Preference* gms_pref =
+        GetGMSPrefFromSetting(pref_service_, setting);
+
+    // Make sure the user prefs are consistent. If the settings are set by
+    // policy, the value of the managed pref will still apply in checks, but
+    // the UPM prefs should contain the user set value.
+    pref_service_->SetBoolean(
+        gms_pref->name(),
+        pref_service_->GetUserPrefValue(regular_pref->name())->GetBool());
+  }
+}
diff --git a/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.h b/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.h
index 8bb45e42..dde706a 100644
--- a/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.h
+++ b/chrome/browser/password_manager/android/password_manager_settings_service_android_impl.h
@@ -57,6 +57,15 @@
   void OnSettingValueAbsent(
       password_manager::PasswordManagerSetting setting) override;
 
+  // Updates the non syncable, android-only prefs with the values of the
+  // syncable cross-platform prefs as the latter won't be used when UPM
+  // is up and running. There is no need to migrate the values until sync turns
+  // on, because UPM is not running until then. When sync turns on, this
+  // will be handled as part of the sync state change rather than migration.
+  // If a migration was already performed, there is no need
+  // to migrate again.
+  void MigratePrefsIfNeeded();
+
   // Pref service used to read and write password manager user prefs.
   raw_ptr<PrefService> pref_service_ = nullptr;
 
diff --git a/chrome/browser/password_manager/android/password_manager_settings_service_android_impl_unittest.cc b/chrome/browser/password_manager/android/password_manager_settings_service_android_impl_unittest.cc
index 7bc6f30..feefb2c 100644
--- a/chrome/browser/password_manager/android/password_manager_settings_service_android_impl_unittest.cc
+++ b/chrome/browser/password_manager/android/password_manager_settings_service_android_impl_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/memory/weak_ptr.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "chrome/browser/password_manager/android/fake_password_manager_lifecycle_helper.h"
 #include "chrome/browser/password_manager/android/password_settings_updater_android_bridge.h"
 #include "components/password_manager/core/browser/password_manager_setting.h"
@@ -51,11 +52,14 @@
   PasswordManagerSettingsServiceAndroidImplTest();
   ~PasswordManagerSettingsServiceAndroidImplTest() override;
 
+  std::unique_ptr<PasswordManagerSettingsServiceAndroidImpl> CreateNewService();
   std::unique_ptr<PasswordManagerSettingsServiceAndroidImpl>
   GetServiceWithoutBackend();
   void SetPasswordsSync(bool enabled);
   void SetSettingsSync(bool enabled);
 
+  void AssertInitialMigrationDidntChangePrefs();
+
   PasswordSettingsUpdaterAndroidBridge::Consumer* updater_bridge_consumer() {
     return settings_service_.get();
   }
@@ -65,6 +69,7 @@
   TestingPrefServiceSimple* pref_service() { return &test_pref_service_; }
   syncer::TestSyncService* sync_service() { return &test_sync_service_; }
   MockPasswordSettingsUpdaterBridge* bridge() { return mock_bridge_; }
+  base::HistogramTester* histogram_tester() { return &histogram_tester_; }
 
  private:
   void RegisterPrefs();
@@ -75,6 +80,7 @@
   syncer::TestSyncService test_sync_service_;
   raw_ptr<MockPasswordSettingsUpdaterBridge> mock_bridge_;
   raw_ptr<FakePasswordManagerLifecycleHelper> fake_lifecycle_helper_;
+  base::HistogramTester histogram_tester_;
 };
 
 PasswordManagerSettingsServiceAndroidImplTest::
@@ -112,6 +118,18 @@
       pref_service(), sync_service(), nullptr, nullptr);
 }
 
+std::unique_ptr<PasswordManagerSettingsServiceAndroidImpl>
+PasswordManagerSettingsServiceAndroidImplTest::CreateNewService() {
+  std::unique_ptr<MockPasswordSettingsUpdaterBridge> bridge =
+      std::make_unique<MockPasswordSettingsUpdaterBridge>();
+  std::unique_ptr<FakePasswordManagerLifecycleHelper> lifecycle_helper =
+      std::make_unique<FakePasswordManagerLifecycleHelper>();
+  return std::make_unique<PasswordManagerSettingsServiceAndroidImpl>(
+      base::PassKey<class PasswordManagerSettingsServiceAndroidImplTest>(),
+      pref_service(), sync_service(), std::move(bridge),
+      std::move(lifecycle_helper));
+}
+
 void PasswordManagerSettingsServiceAndroidImplTest::SetPasswordsSync(
     bool enabled) {
   syncer::UserSelectableTypeSet selected_sync_types =
@@ -138,6 +156,22 @@
                                                          selected_sync_types);
 }
 
+void PasswordManagerSettingsServiceAndroidImplTest::
+    AssertInitialMigrationDidntChangePrefs() {
+  // A migration already happened when the service was created in the test
+  // constructor, however because all prefs had default values, their values
+  // remained the same. Only the migration pref was set to true, signaling
+  // that the migration was executed.
+  ASSERT_EQ(pref_service()->GetUserPrefValue(
+                password_manager::prefs::kOfferToSavePasswordsEnabledGMS),
+            nullptr);
+  ASSERT_EQ(pref_service()->GetUserPrefValue(
+                password_manager::prefs::kAutoSignInEnabledGMS),
+            nullptr);
+  ASSERT_TRUE(pref_service()->GetBoolean(
+      password_manager::prefs::kSettingsMigratedToUPM));
+}
+
 void PasswordManagerSettingsServiceAndroidImplTest::RegisterPrefs() {
   test_pref_service_.registry()->RegisterBooleanPref(
       password_manager::prefs::kCredentialsEnableService, true);
@@ -147,6 +181,130 @@
       password_manager::prefs::kOfferToSavePasswordsEnabledGMS, true);
   test_pref_service_.registry()->RegisterBooleanPref(
       password_manager::prefs::kAutoSignInEnabledGMS, true);
+
+  test_pref_service_.registry()->RegisterBooleanPref(
+      password_manager::prefs::kSettingsMigratedToUPM, false);
+}
+
+TEST_F(PasswordManagerSettingsServiceAndroidImplTest,
+       TestNoAdditionalMigration) {
+  AssertInitialMigrationDidntChangePrefs();
+
+  // No additional migration should happen if the migration pref wasn't reset.
+  CreateNewService();
+  histogram_tester()->ExpectUniqueSample(
+      "PasswordManager.MigratedSettingsUPMAndroid", true, 1);
+  EXPECT_EQ(pref_service()->GetUserPrefValue(
+                password_manager::prefs::kOfferToSavePasswordsEnabledGMS),
+            nullptr);
+  EXPECT_EQ(pref_service()->GetUserPrefValue(
+                password_manager::prefs::kAutoSignInEnabledGMS),
+            nullptr);
+  EXPECT_TRUE(pref_service()->GetBoolean(
+      password_manager::prefs::kSettingsMigratedToUPM));
+}
+
+TEST_F(PasswordManagerSettingsServiceAndroidImplTest,
+       TestNewMigrationIfPrefUndoneSyncOff) {
+  AssertInitialMigrationDidntChangePrefs();
+
+  // Reset the migration pref.
+  pref_service()->SetBoolean(password_manager::prefs::kSettingsMigratedToUPM,
+                             false);
+  // Set an explicit value on the "Offer to save passwords" pref.
+  pref_service()->SetBoolean(password_manager::prefs::kCredentialsEnableService,
+                             false);
+
+  // No migration should happen if passwords sync is off, but the migration
+  // should be marked as done.
+  SetPasswordsSync(false);
+  CreateNewService();
+  histogram_tester()->ExpectUniqueSample(
+      "PasswordManager.MigratedSettingsUPMAndroid", true, 2);
+  EXPECT_EQ(pref_service()->GetUserPrefValue(
+                password_manager::prefs::kOfferToSavePasswordsEnabledGMS),
+            nullptr);
+  EXPECT_EQ(pref_service()->GetUserPrefValue(
+                password_manager::prefs::kAutoSignInEnabledGMS),
+            nullptr);
+  EXPECT_TRUE(pref_service()->GetBoolean(
+      password_manager::prefs::kSettingsMigratedToUPM));
+}
+
+TEST_F(PasswordManagerSettingsServiceAndroidImplTest,
+       TestNewMigrationIfPrefUndoneSyncOn) {
+  AssertInitialMigrationDidntChangePrefs();
+
+  // Reset the migration pref.
+  pref_service()->SetBoolean(password_manager::prefs::kSettingsMigratedToUPM,
+                             false);
+  // Set an explicit value on the "Offer to save passwords" pref.
+  pref_service()->SetBoolean(password_manager::prefs::kCredentialsEnableService,
+                             false);
+
+  // Migration changes are expected if sync is on when the service is created.
+  SetPasswordsSync(true);
+  CreateNewService();
+  histogram_tester()->ExpectUniqueSample(
+      "PasswordManager.MigratedSettingsUPMAndroid", true, 2);
+  EXPECT_FALSE(pref_service()->GetBoolean(
+      password_manager::prefs::kOfferToSavePasswordsEnabledGMS));
+  EXPECT_EQ(pref_service()->GetUserPrefValue(
+                password_manager::prefs::kAutoSignInEnabledGMS),
+            nullptr);
+}
+
+TEST_F(PasswordManagerSettingsServiceAndroidImplTest,
+       TestNewMigrationManagedPrefSetValue) {
+  AssertInitialMigrationDidntChangePrefs();
+
+  // Reset the migration pref.
+  pref_service()->SetBoolean(password_manager::prefs::kSettingsMigratedToUPM,
+                             false);
+  // Set an explicit value on the "Offer to save passwords" pref.
+  pref_service()->SetBoolean(password_manager::prefs::kCredentialsEnableService,
+                             true);
+  // Saving passwords is disabled by policy.
+  pref_service()->SetManagedPref(
+      password_manager::prefs::kCredentialsEnableService, base::Value(false));
+
+  // Create a new service and expect that the migration stores the user value,
+  // not the one enforced by policy.
+  CreateNewService();
+  histogram_tester()->ExpectUniqueSample(
+      "PasswordManager.MigratedSettingsUPMAndroid", true, 2);
+  EXPECT_TRUE(pref_service()->GetBoolean(
+      password_manager::prefs::kSettingsMigratedToUPM));
+  EXPECT_TRUE(pref_service()->GetBoolean(
+      password_manager::prefs::kOfferToSavePasswordsEnabledGMS));
+  EXPECT_NE(pref_service()->GetUserPrefValue(
+                password_manager::prefs::kOfferToSavePasswordsEnabledGMS),
+            nullptr);
+}
+
+TEST_F(PasswordManagerSettingsServiceAndroidImplTest,
+       TestNewMigrationManagedPrefDefaultValue) {
+  AssertInitialMigrationDidntChangePrefs();
+
+  // Reset the migration pref.
+  pref_service()->SetBoolean(password_manager::prefs::kSettingsMigratedToUPM,
+                             false);
+  // Saving passwords is disabled by policy.
+  pref_service()->SetManagedPref(
+      password_manager::prefs::kCredentialsEnableService, base::Value(false));
+
+  // Create a new service and expect that the migration doesn't change the
+  // GMS pref value, because the user hasn't set any value.
+  CreateNewService();
+  histogram_tester()->ExpectUniqueSample(
+      "PasswordManager.MigratedSettingsUPMAndroid", true, 2);
+  EXPECT_TRUE(pref_service()->GetBoolean(
+      password_manager::prefs::kSettingsMigratedToUPM));
+  EXPECT_TRUE(pref_service()->GetBoolean(
+      password_manager::prefs::kOfferToSavePasswordsEnabledGMS));
+  EXPECT_EQ(pref_service()->GetUserPrefValue(
+                password_manager::prefs::kOfferToSavePasswordsEnabledGMS),
+            nullptr);
 }
 
 TEST_F(PasswordManagerSettingsServiceAndroidImplTest,
diff --git a/chrome/browser/password_manager/password_manager_settings_service_factory.cc b/chrome/browser/password_manager/password_manager_settings_service_factory.cc
index c71a83d..335c80c 100644
--- a/chrome/browser/password_manager/password_manager_settings_service_factory.cc
+++ b/chrome/browser/password_manager/password_manager_settings_service_factory.cc
@@ -13,6 +13,8 @@
 #include "components/password_manager/core/common/password_manager_features.h"
 #if BUILDFLAG(IS_ANDROID)
 #include "chrome/browser/password_manager/android/password_manager_settings_service_android_impl.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_service.h"
 #endif
 
 // static
@@ -46,6 +48,10 @@
     return new PasswordManagerSettingsServiceAndroidImpl(
         profile->GetPrefs(), SyncServiceFactory::GetForProfile(profile));
   }
+  // Reset the migration pref in case the client is no longer in the enabled
+  // group.
+  profile->GetPrefs()->SetBoolean(
+      password_manager::prefs::kSettingsMigratedToUPM, false);
   return new PasswordManagerSettingsServiceImpl(profile->GetPrefs());
 #else
   return new PasswordManagerSettingsServiceImpl(profile->GetPrefs());
diff --git a/chrome/browser/password_manager/password_manager_signin_intercept_test_helper.cc b/chrome/browser/password_manager/password_manager_signin_intercept_test_helper.cc
index dd788ca..d74dbcb0f 100644
--- a/chrome/browser/password_manager/password_manager_signin_intercept_test_helper.cc
+++ b/chrome/browser/password_manager/password_manager_signin_intercept_test_helper.cc
@@ -80,7 +80,7 @@
   std::string path = "/password/password_form.html";
   GURL https_url(https_test_server_->GetURL(path));
   DCHECK(https_url.SchemeIs(url::kHttpsScheme));
-  DCHECK(gaia::IsGaiaSignonRealm(https_url.DeprecatedGetOriginAsURL()));
+  DCHECK(gaia::HasGaiaSchemeHostPort(https_url));
 
   PasswordsNavigationObserver navigation_observer(contents);
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 38fee91c..9c7234dba 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -4299,15 +4299,7 @@
                          testing::ValuesIn(GetAXTestValues()),
                          PDFExtensionAccessibilityTreeDumpTestPassToString());
 
-// TODO(crbug.com/1324362): Fix Mac flakes.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_HelloWorld DISABLED_HelloWorld
-#else
-#define MAYBE_HelloWorld HelloWorld
-#endif
-
-IN_PROC_BROWSER_TEST_P(PDFExtensionAccessibilityTreeDumpTest,
-                       MAYBE_HelloWorld) {
+IN_PROC_BROWSER_TEST_P(PDFExtensionAccessibilityTreeDumpTest, HelloWorld) {
   RunPDFTest(FILE_PATH_LITERAL("hello-world.pdf"));
 }
 
@@ -4342,15 +4334,7 @@
   RunPDFTest(FILE_PATH_LITERAL("highlights.pdf"));
 }
 
-// TODO(crbug.com/1324362): Fix Mac flakes.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_TextFields DISABLED_TextFields
-#else
-#define MAYBE_TextFields TextFields
-#endif
-
-IN_PROC_BROWSER_TEST_P(PDFExtensionAccessibilityTreeDumpTest,
-                       MAYBE_TextFields) {
+IN_PROC_BROWSER_TEST_P(PDFExtensionAccessibilityTreeDumpTest, TextFields) {
   RunPDFTest(FILE_PATH_LITERAL("text_fields.pdf"));
 }
 
diff --git a/chrome/browser/permissions/permission_request_manager_browsertest.cc b/chrome/browser/permissions/permission_request_manager_browsertest.cc
index 1f410db..f4b161b 100644
--- a/chrome/browser/permissions/permission_request_manager_browsertest.cc
+++ b/chrome/browser/permissions/permission_request_manager_browsertest.cc
@@ -38,7 +38,7 @@
 #include "components/permissions/test/mock_permission_prompt_factory.h"
 #include "components/permissions/test/mock_permission_request.h"
 #include "components/variations/variations_associated_data.h"
-#include "content/public/browser/permission_controller_delegate.h"
+#include "content/public/browser/permission_controller.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
@@ -1235,10 +1235,12 @@
 
   base::MockOnceCallback<void(blink::mojom::PermissionStatus)> callback;
   EXPECT_CALL(callback, Run(blink::mojom::PermissionStatus::DENIED));
-  auto* delegate = browser()->profile()->GetPermissionControllerDelegate();
-  delegate->RequestPermission(blink::PermissionType::SENSORS, fenced_frame_host,
-                              fenced_frame_url,
-                              /* user_gesture = */ true, callback.Get());
+
+  content::PermissionController* permission_controller =
+      browser()->profile()->GetPermissionController();
+  permission_controller->RequestPermissionFromCurrentDocument(
+      blink::PermissionType::SENSORS, fenced_frame_host,
+      /* user_gesture = */ true, callback.Get());
   console_observer.Wait();
   ASSERT_EQ(1u, console_observer.messages().size());
 }
diff --git a/chrome/browser/permissions/permissions_security_model_interactive_uitest.cc b/chrome/browser/permissions/permissions_security_model_interactive_uitest.cc
index d626be3b..9670aa74 100644
--- a/chrome/browser/permissions/permissions_security_model_interactive_uitest.cc
+++ b/chrome/browser/permissions/permissions_security_model_interactive_uitest.cc
@@ -901,25 +901,8 @@
   EXPECT_EQ("https://chromium.org/", main_rfh->GetLastCommittedURL().spec());
   EXPECT_TRUE(main_rfh->GetLastCommittedOrigin().GetURL().SchemeIsFile());
 
-  const struct {
-    std::string check_permission;
-    std::string request_permission;
-  } kTests[] = {
-      {kCheckCamera, kRequestCamera},
-      {kCheckGeolocation, kRequestGeolocation},
-  };
-
-  for (const auto& test : kTests) {
-    ASSERT_FALSE(
-        content::EvalJs(main_rfh, test.check_permission).value.GetBool());
-    EXPECT_EQ("granted", content::EvalJs(main_rfh, test.request_permission));
-    ASSERT_TRUE(
-        content::EvalJs(main_rfh, test.check_permission).value.GetBool());
-  }
-
-  // Notifications is not supported for file:/// with changed URL.
-  ASSERT_FALSE(content::EvalJs(main_rfh, kCheckNotifications).value.GetBool());
-  EXPECT_EQ("denied", content::EvalJs(main_rfh, kRequestNotifications));
+  // `https://chromium.org` is used for permissions verification.
+  VerifyPermissionsAllowed(main_rfh);
 }
 
 // Verifies that permissions are not supported for file:/// with changed URL to
diff --git a/chrome/browser/send_tab_to_self/send_tab_to_self_util.cc b/chrome/browser/send_tab_to_self/send_tab_to_self_util.cc
index 9835860..5932217 100644
--- a/chrome/browser/send_tab_to_self/send_tab_to_self_util.cc
+++ b/chrome/browser/send_tab_to_self/send_tab_to_self_util.cc
@@ -14,7 +14,6 @@
 #include "components/signin/public/base/signin_pref_names.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/sync/driver/sync_service.h"
-#include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 #include "url/gurl.h"
 
@@ -37,10 +36,7 @@
   if (!web_contents)
     return absl::nullopt;
 
-  if (!web_contents->GetURL().SchemeIsHTTPOrHTTPS())
-    return absl::nullopt;
-
-  if (!web_contents->GetController().GetLastCommittedEntry())
+  if (!web_contents->GetLastCommittedURL().SchemeIsHTTPOrHTTPS())
     return absl::nullopt;
 
   Profile* profile =
diff --git a/chrome/browser/signin/chrome_signin_helper.cc b/chrome/browser/signin/chrome_signin_helper.cc
index ed96e4a..b19b9cd 100644
--- a/chrome/browser/signin/chrome_signin_helper.cc
+++ b/chrome/browser/signin/chrome_signin_helper.cc
@@ -159,8 +159,7 @@
   }
 
   return request->IsFetchLikeAPI() &&
-         gaia::IsGaiaSignonRealm(
-             request->GetReferrer().DeprecatedGetOriginAsURL());
+         gaia::HasGaiaSchemeHostPort(request->GetReferrer());
 }
 
 #endif  // BUILDFLAG(ENABLE_DICE_SUPPORT)
@@ -453,7 +452,7 @@
 // child/route id. Must be called on IO thread.
 void ProcessMirrorResponseHeaderIfExists(ResponseAdapter* response,
                                          bool is_off_the_record) {
-  CHECK(gaia::IsGaiaSignonRealm(response->GetURL().DeprecatedGetOriginAsURL()));
+  CHECK(gaia::HasGaiaSchemeHostPort(response->GetURL()));
 
   if (!response->IsOutermostMainFrame())
     return;
@@ -503,7 +502,7 @@
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
 void ProcessDiceResponseHeaderIfExists(ResponseAdapter* response,
                                        bool is_off_the_record) {
-  CHECK(gaia::IsGaiaSignonRealm(response->GetURL().DeprecatedGetOriginAsURL()));
+  CHECK(gaia::HasGaiaSchemeHostPort(response->GetURL()));
 
   if (is_off_the_record)
     return;
@@ -564,7 +563,7 @@
 
 void ProcessRemoveLocalAccountResponseHeaderIfExists(ResponseAdapter* response,
                                                      bool is_off_the_record) {
-  CHECK(gaia::IsGaiaSignonRealm(response->GetURL().DeprecatedGetOriginAsURL()));
+  CHECK(gaia::HasGaiaSchemeHostPort(response->GetURL()));
 
   if (is_off_the_record)
     return;
@@ -679,7 +678,7 @@
 void ProcessAccountConsistencyResponseHeaders(ResponseAdapter* response,
                                               const GURL& redirect_url,
                                               bool is_off_the_record) {
-  if (!gaia::IsGaiaSignonRealm(response->GetURL().DeprecatedGetOriginAsURL()))
+  if (!gaia::HasGaiaSchemeHostPort(response->GetURL()))
     return;
 
 #if BUILDFLAG(ENABLE_MIRROR)
diff --git a/chrome/browser/signin/dice_tab_helper.cc b/chrome/browser/signin/dice_tab_helper.cc
index 4e538d31..20dc6c08 100644
--- a/chrome/browser/signin/dice_tab_helper.cc
+++ b/chrome/browser/signin/dice_tab_helper.cc
@@ -12,7 +12,7 @@
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/navigation_handle.h"
-#include "google_apis/gaia/gaia_urls.h"
+#include "google_apis/gaia/gaia_auth_util.h"
 
 DiceTabHelper::DiceTabHelper(content::WebContents* web_contents)
     : content::WebContentsUserData<DiceTabHelper>(*web_contents),
@@ -110,8 +110,7 @@
     content::NavigationHandle* navigation_handle) const {
   return !navigation_handle->IsErrorPage() &&
          navigation_handle->GetRedirectChain()[0] == signin_url_ &&
-         navigation_handle->GetURL().DeprecatedGetOriginAsURL() ==
-             GaiaUrls::GetInstance()->gaia_url();
+         gaia::HasGaiaSchemeHostPort(navigation_handle->GetURL());
 }
 
 WEB_CONTENTS_USER_DATA_KEY_IMPL(DiceTabHelper);
diff --git a/chrome/browser/site_isolation/isolated_sandboxed_iframe_browsertest.cc b/chrome/browser/site_isolation/isolated_sandboxed_iframe_browsertest.cc
new file mode 100644
index 0000000..a54cb56
--- /dev/null
+++ b/chrome/browser/site_isolation/isolated_sandboxed_iframe_browsertest.cc
@@ -0,0 +1,659 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/feature_list.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/metrics/metrics_memory_details.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/network_session_configurator/common/network_switches.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_mock_cert_verifier.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/gurl.h"
+
+class TestMemoryDetails : public MetricsMemoryDetails {
+ public:
+  TestMemoryDetails() : MetricsMemoryDetails(base::DoNothing()) {}
+
+  TestMemoryDetails(const TestMemoryDetails&) = delete;
+  TestMemoryDetails& operator=(const TestMemoryDetails&) = delete;
+
+  void StartFetchAndWait() {
+    uma_ = std::make_unique<base::HistogramTester>();
+    StartFetch();
+    run_loop_.Run();
+  }
+
+  // Assumes we've just finished calling StartFetchAndWait(), and there is at
+  // most one sample recorded for `metric`.
+  void VerifyMetricResult(const std::string& metric, int value, int count) {
+    std::vector<base::Bucket> histogram_for_metric =
+        uma_->GetAllSamples(metric);
+    if (histogram_for_metric.size()) {
+      EXPECT_EQ(base::Bucket(value, count), histogram_for_metric[0])
+          << " : metric = " << metric;
+    } else {
+      EXPECT_EQ(0, count) << " : metric = " << metric;
+    }
+  }
+
+  // Returns a HistogramTester which observed the most recent call to
+  // StartFetchAndWait().
+  base::HistogramTester* uma() { return uma_.get(); }
+
+ private:
+  ~TestMemoryDetails() override = default;
+
+  void OnDetailsAvailable() override {
+    MetricsMemoryDetails::OnDetailsAvailable();
+    // Exit the loop initiated by StartFetchAndWait().
+    run_loop_.QuitWhenIdle();
+  }
+
+  std::unique_ptr<base::HistogramTester> uma_;
+  base::RunLoop run_loop_;
+};
+
+class IsolatedSandboxedIframeBrowserTest : public InProcessBrowserTest {
+ public:
+  IsolatedSandboxedIframeBrowserTest()
+      : IsolatedSandboxedIframeBrowserTest(
+            true /* enable_isolate_sandboxed_iframes */) {
+    // To keep the tests easier to reason about, turn off both the spare
+    // renderer process and process reuse for subframes in different
+    // BrowsingInstances.
+    if (enable_isolate_sandboxed_iframes_) {
+      feature_list_.InitWithFeatures(
+          /* enable_features */ {features::kIsolateSandboxedIframes,
+                                 features::kDisableProcessReuse},
+          /* disable_features */ {features::kSpareRendererForSitePerProcess});
+    } else {
+      feature_list_.InitWithFeatures(
+          /* enable_features */ {features::kDisableProcessReuse},
+          /* disable_features */ {features::kIsolateSandboxedIframes,
+                                  features::kSpareRendererForSitePerProcess});
+    }
+  }
+
+  IsolatedSandboxedIframeBrowserTest(
+      const IsolatedSandboxedIframeBrowserTest&) = delete;
+  IsolatedSandboxedIframeBrowserTest& operator=(
+      const IsolatedSandboxedIframeBrowserTest&) = delete;
+
+  ~IsolatedSandboxedIframeBrowserTest() override = default;
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    mock_cert_verifier_.SetUpCommandLine(command_line);
+    ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
+    https_server()->AddDefaultHandlers(GetChromeTestDataDir());
+    ASSERT_TRUE(https_server()->Start());
+  }
+
+  void SetUpOnMainThread() override {
+    host_resolver()->AddRule("*", "127.0.0.1");
+    embedded_test_server()->StartAcceptingConnections();
+  }
+
+  void SetUpInProcessBrowserTestFixture() override {
+    mock_cert_verifier_.SetUpInProcessBrowserTestFixture();
+  }
+
+  void TearDownInProcessBrowserTestFixture() override {
+    mock_cert_verifier_.TearDownInProcessBrowserTestFixture();
+  }
+
+  void TearDownOnMainThread() override {
+    ASSERT_TRUE(https_server()->ShutdownAndWaitUntilComplete());
+  }
+
+  net::EmbeddedTestServer* https_server() { return &https_server_; }
+
+  void VerifyStartupMetrics() {
+    scoped_refptr<TestMemoryDetails> details = new TestMemoryDetails();
+    details->StartFetchAndWait();
+
+    // Verify we're starting at zero.
+    details->VerifyMetricResult("SiteIsolation.IsolatableSandboxedIframes",
+                                0 /* value */, 1 /* count*/);
+    details->VerifyMetricResult(
+        "SiteIsolation.IsolatableSandboxedIframes.UniqueOrigins", 0 /* value */,
+        1 /* count*/);
+    details->VerifyMetricResult(
+        "SiteIsolation.IsolatableSandboxedIframes.UniqueSites", 0 /* value */,
+        1 /* count*/);
+    details->VerifyMetricResult(
+        "Memory.RenderProcessHost.Count.SandboxedIframeOverhead", 0 /* value */,
+        1 /* count*/);
+  }
+
+  void VerifyMetrics(int isolatable_sandboxed_iframes_value,
+                     int unique_origins_value,
+                     int unique_sites_value,
+                     int process_overhead_value) {
+    scoped_refptr<TestMemoryDetails> details = new TestMemoryDetails();
+    details->StartFetchAndWait();
+
+    details->VerifyMetricResult("SiteIsolation.IsolatableSandboxedIframes",
+                                isolatable_sandboxed_iframes_value,
+                                1 /* count*/);
+    details->VerifyMetricResult(
+        "SiteIsolation.IsolatableSandboxedIframes.UniqueOrigins",
+        unique_origins_value, 1 /* count*/);
+    details->VerifyMetricResult(
+        "SiteIsolation.IsolatableSandboxedIframes.UniqueSites",
+        unique_sites_value, 1 /* count*/);
+    details->VerifyMetricResult(
+        "Memory.RenderProcessHost.Count.SandboxedIframeOverhead",
+        process_overhead_value, 1 /* count*/);
+  }
+
+ protected:
+  explicit IsolatedSandboxedIframeBrowserTest(
+      bool enable_isolate_sandboxed_iframes)
+      : https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
+        enable_isolate_sandboxed_iframes_(enable_isolate_sandboxed_iframes) {}
+
+ private:
+  content::ContentMockCertVerifier mock_cert_verifier_;
+  net::EmbeddedTestServer https_server_;
+  base::test::ScopedFeatureList feature_list_;
+  bool enable_isolate_sandboxed_iframes_;
+};  // class IsolatedSandboxedIframeBrowserTest
+
+class NotIsolatedSandboxedIframeBrowserTest
+    : public IsolatedSandboxedIframeBrowserTest {
+ public:
+  NotIsolatedSandboxedIframeBrowserTest()
+      : IsolatedSandboxedIframeBrowserTest(
+            false /* enable_isolate_sandboxed_iframes */) {}
+
+  NotIsolatedSandboxedIframeBrowserTest(
+      const NotIsolatedSandboxedIframeBrowserTest&) = delete;
+  NotIsolatedSandboxedIframeBrowserTest& operator=(
+      const NotIsolatedSandboxedIframeBrowserTest&) = delete;
+
+  ~NotIsolatedSandboxedIframeBrowserTest() override = default;
+};  // class NotIsolatedSandboxedIframeBrowserTest
+
+// Test that a single isolatable frame generates correct metrics.
+IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, IsolatedSandbox) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  // The child needs to have the same origin as the parent.
+  GURL child_url(main_url);
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  content::RenderFrameHost* frame_host = web_contents->GetMainFrame();
+
+  VerifyStartupMetrics();
+
+  // Create sandboxed child frame, same-origin.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.sandbox = ''; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        child_url.spec().c_str());
+    EXPECT_TRUE(ExecuteScript(frame_host, js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents));
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 1;
+  int unique_origins_value = 1;
+  int unique_sites_value = 1;
+  int process_overhead_value = 1;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// Test to verify that two isolatable frames from one origin generate the
+// correct metrics.
+IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest,
+                       IsolatedSandboxSiblingSubframes) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  // The child needs to have the same origin as the parent.
+  GURL child_url(main_url);
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  content::RenderFrameHost* frame_host = web_contents->GetMainFrame();
+
+  VerifyStartupMetrics();
+
+  // Create sandboxed child frame, same-origin.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame1 = document.createElement('iframe'); "
+        "frame1.sandbox = ''; "
+        "frame1.src = '%s'; "
+        "document.body.appendChild(frame1); "
+        "var frame2 = document.createElement('iframe'); "
+        "frame2.sandbox = ''; "
+        "frame2.src = '%s'; "
+        "document.body.appendChild(frame2);",
+        child_url.spec().c_str(), child_url.spec().c_str());
+    EXPECT_TRUE(ExecuteScript(frame_host, js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents));
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 2;
+  int unique_origins_value = 1;
+  int unique_sites_value = 1;
+  int process_overhead_value = 1;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// A test to exercise the case where the number of origins, sites, and
+// isolatable iframes are all different.
+IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest,
+                       IsolatedSandbox3Frames2Origins1Site) {
+  GURL main_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+  GURL child_url_a(embedded_test_server()->GetURL("a.foo.com", "/title1.html"));
+  GURL child_url_b(embedded_test_server()->GetURL("b.foo.com", "/title1.html"));
+
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  content::RenderFrameHost* frame_host = web_contents->GetMainFrame();
+
+  VerifyStartupMetrics();
+
+  // Create three sandboxed child frames, same-site but two unique origins.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame1 = document.createElement('iframe'); "
+        "frame1.sandbox = ''; "
+        "frame1.src = '%s'; "
+        "document.body.appendChild(frame1); "
+        "var frame2 = document.createElement('iframe'); "
+        "frame2.sandbox = ''; "
+        "frame2.src = '%s'; "
+        "document.body.appendChild(frame2);"
+        "var frame3 = document.createElement('iframe'); "
+        "frame3.sandbox = ''; "
+        "frame3.src = '%s'; "
+        "document.body.appendChild(frame3);",
+        child_url_a.spec().c_str(), child_url_b.spec().c_str(),
+        child_url_b.spec().c_str());
+    EXPECT_TRUE(ExecuteScript(frame_host, js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents));
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 3;
+  int unique_origins_value = 2;
+  int unique_sites_value = 1;
+  int process_overhead_value = 1;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// A test to verify that the metrics for process overhead pick up multiple
+// processes for sandboxed iframes associated with different sites.
+IN_PROC_BROWSER_TEST_F(
+    IsolatedSandboxedIframeBrowserTest,
+    IsolatedSandboxOverheadMetricsForDifferentSiteSandboxFrames) {
+  GURL main_url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  GURL child_url_a(main_url_a);
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url_a));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  content::RenderFrameHost* frame_host = web_contents->GetMainFrame();
+
+  VerifyStartupMetrics();
+
+  // Create sandboxed child frame, same-origin.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.sandbox = ''; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        child_url_a.spec().c_str());
+    EXPECT_TRUE(ExecuteScript(frame_host, js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents));
+  }
+
+  // Open a second tab on a different site, with an isolatable sandboxed iframe.
+  GURL main_url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
+  GURL child_url_b(main_url_b);
+  ASSERT_TRUE(AddTabAtIndex(1, main_url_b, ui::PAGE_TRANSITION_TYPED));
+  content::WebContents* web_contents_b =
+      browser()->tab_strip_model()->GetWebContentsAt(1);
+
+  // Create sandboxed child frame, same-origin.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.sandbox = ''; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        child_url_b.spec().c_str());
+    EXPECT_TRUE(ExecuteScript(web_contents_b->GetMainFrame(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents_b));
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 2;
+  int unique_origins_value = 2;
+  int unique_sites_value = 2;
+  int process_overhead_value = 2;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// Test to verify that a srcdoc sandboxed iframe generates the correct metrics.
+IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest,
+                       IsolatedSandboxSrcdocSubframe) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  VerifyStartupMetrics();
+
+  // Create sandboxed child frame, with srcdoc content.
+  std::string child_inner_text("srcdoc sandboxed subframe");
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.sandbox = 'allow-scripts'; "
+        "frame.srcdoc = '%s'; "
+        "document.body.appendChild(frame);",
+        child_inner_text.c_str());
+    EXPECT_TRUE(ExecuteScript(web_contents->GetMainFrame(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents));
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 1;
+  int unique_origins_value = 1;
+  int unique_sites_value = 1;
+  int process_overhead_value = 1;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// Test to verify that a sandboxed iframes with about:blank doesn't get counted
+// in the metrics.
+IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest,
+                       NotIsolatedSandboxAboutBlankSubframe) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  VerifyStartupMetrics();
+
+  // Create sandboxed child frame, with about:blank content.
+  {
+    std::string js_str(
+        "var frame = document.createElement('iframe'); "
+        "frame.id = 'child_frame'; "
+        "frame.sandbox = ''; "
+        "frame.src = 'about:blank'; "
+        "document.body.appendChild(frame);");
+    EXPECT_TRUE(ExecuteScript(web_contents->GetMainFrame(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents));
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 0;
+  int unique_origins_value = 0;
+  int unique_sites_value = 0;
+  int process_overhead_value = 0;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// Test to verify that a sandboxed iframe with an empty url (nothing committed)
+// doesn't get counted in the metrics.
+IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest,
+                       NotIsolatedSandboxEmptyUrlSubframe) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  VerifyStartupMetrics();
+
+  // Create sandboxed child frame, with about:blank content.
+  {
+    GURL empty_url(embedded_test_server()->GetURL("a.com", "/page204.html"));
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.id = 'child_frame'; "
+        "frame.sandbox = ''; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        empty_url.spec().c_str());
+    EXPECT_TRUE(ExecuteScript(web_contents->GetMainFrame(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents));
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 0;
+  int unique_origins_value = 0;
+  int unique_sites_value = 0;
+  int process_overhead_value = 0;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// Test to verify that a javascript: sandboxed iframe does not generate any
+// metrics.
+IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest,
+                       SandboxedIframeWithJSUrl) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  VerifyStartupMetrics();
+
+  // Create sandboxed child frame with a javascript: URL.
+  std::string js_url_str("javascript:\"foo\"");
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.id = 'test_frame'; "
+        "frame.sandbox = 'allow-scripts'; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        js_url_str.c_str());
+    EXPECT_TRUE(ExecuteScript(web_contents->GetMainFrame(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents));
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 0;
+  int unique_origins_value = 0;
+  int unique_sites_value = 0;
+  int process_overhead_value = 0;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// Verify that when the flag for isolating sandboxed iframe is off, we collect
+// metrics for isolatable iframe count and number of unique origins, but no
+// metrics for actual process overhead.
+IN_PROC_BROWSER_TEST_F(NotIsolatedSandboxedIframeBrowserTest, IsolatedSandbox) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  // The child needs to have the same origin as the parent.
+  GURL child_url(main_url);
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  VerifyStartupMetrics();
+
+  // Create sandboxed child frame, same-origin.
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.sandbox = ''; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        child_url.spec().c_str());
+    EXPECT_TRUE(ExecuteScript(web_contents->GetMainFrame(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents));
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 1;
+  int unique_origins_value = 1;
+  int unique_sites_value = 1;
+  int process_overhead_value = 0;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// Test to make sure that a sandboxed mainframe is considered isolatable if it
+// has a same-site opener.
+IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest,
+                       SandboxedMainframeWithSameSiteOpener) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  GURL child_url(main_url);
+  GURL popup_url(main_url);
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  VerifyStartupMetrics();
+
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.id = 'test_frame'; "
+        "frame.sandbox = 'allow-popups allow-scripts'; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        child_url.spec().c_str());
+    EXPECT_TRUE(ExecuteScript(web_contents->GetMainFrame(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents));
+  }
+
+  // Open popup from sandboxed iframe. This creates a sandboxed mainframe that
+  // is isolatable. We make sure the popup url is same-site to the opener,
+  // otherwise it would just create an OOPIF.
+  content::RenderFrameHost* child_rfh =
+      ChildFrameAt(web_contents->GetMainFrame(), 0);
+  {
+    std::string js_str =
+        base::StringPrintf("window.open('%s');", popup_url.spec().c_str());
+
+    content::TestNavigationObserver popup_observer(nullptr);
+    popup_observer.StartWatchingNewWebContents();
+    EXPECT_TRUE(ExecuteScript(child_rfh, js_str));
+    popup_observer.Wait();
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 2;
+  int unique_origins_value = 1;
+  int unique_sites_value = 1;
+  int process_overhead_value = 1;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// Test to make sure that a CSP sandboxed mainframe is considered isolatable
+// when opened by a non-sandboxed parent.
+IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest,
+                       CspSandboxedMainframeWithSameSiteOpener) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  GURL popup_url(
+      embedded_test_server()->GetURL("a.com", "/cryptotoken/csp-sandbox.html"));
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  VerifyStartupMetrics();
+
+  // Open popup from (non-sandboxed) main frame. The popup will arrive with a
+  // CSP sandbox header, and so will be marked isolatable since it is same-site
+  // to its opener.
+  {
+    std::string js_str =
+        base::StringPrintf("window.open('%s');", popup_url.spec().c_str());
+
+    content::TestNavigationObserver popup_observer(nullptr);
+    popup_observer.StartWatchingNewWebContents();
+    EXPECT_TRUE(ExecuteScript(web_contents->GetMainFrame(), js_str));
+    popup_observer.Wait();
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 1;
+  int unique_origins_value = 1;
+  int unique_sites_value = 1;
+  int process_overhead_value = 1;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// Test to make sure that a CSP sandboxed mainframe is not considered isolatable
+// when when visited directly.
+IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest,
+                       CspSandboxedMainframeVisitedDirectly) {
+  GURL main_url(
+      embedded_test_server()->GetURL("a.com", "/cryptotoken/csp-sandbox.html"));
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 0;
+  int unique_origins_value = 0;
+  int unique_sites_value = 0;
+  int process_overhead_value = 0;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
+
+// Test to make sure that an iframe with a data:url is appropriately counted by
+// the sandbox isolation metrics.
+IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest,
+                       SandboxedIframeWithDataURL) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  VerifyStartupMetrics();
+
+  // Create sandboxed child frame with a data URL.
+  std::string data_url_str("data:text/html,dataurl");
+  {
+    std::string js_str = base::StringPrintf(
+        "var frame = document.createElement('iframe'); "
+        "frame.id = 'test_frame'; "
+        "frame.sandbox = ''; "
+        "frame.src = '%s'; "
+        "document.body.appendChild(frame);",
+        data_url_str.c_str());
+    EXPECT_TRUE(ExecuteScript(web_contents->GetMainFrame(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(web_contents));
+  }
+
+  // Verify histograms are updated.
+  int isolatable_sandboxed_iframes_value = 1;
+  int unique_origins_value = 1;
+  int unique_sites_value = 1;
+  int process_overhead_value = 1;
+  VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value,
+                unique_sites_value, process_overhead_value);
+}
diff --git a/chrome/browser/site_isolation/site_details.cc b/chrome/browser/site_isolation/site_details.cc
index 354df0a3..f9eda07 100644
--- a/chrome/browser/site_isolation/site_details.cc
+++ b/chrome/browser/site_isolation/site_details.cc
@@ -153,6 +153,11 @@
   base::UmaHistogramCounts100("SiteIsolation.OutOfProcessIframes", num_oopifs);
   base::UmaHistogramCounts100("SiteIsolation.OutOfProcessInnerFrameTrees",
                               num_oop_inner_frame_trees);
+
+  // Log metrics related to the actual & potential process overhead of isolated
+  // sandboxed iframes.
+  RenderFrameHost::LogSandboxedIframesIsolationMetrics();
+
   if (!content::SiteIsolationPolicy::
           IsProcessIsolationForOriginAgentClusterEnabled()) {
     return;
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_api.cc b/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
index 5d506275..dfb3e33 100644
--- a/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
+++ b/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
@@ -336,51 +336,44 @@
       voice.events.find(content::TTS_EVENT_END) != voice.events.end();
 
   std::unique_ptr<base::ListValue> args(new base::ListValue());
-  args->Append(utterance->GetText());
+  args->GetList().Append(utterance->GetText());
 
   // Pass through most options to the speech engine, but remove some
   // that are handled internally.
-  std::unique_ptr<base::DictionaryValue> options = base::DictionaryValue::From(
-      base::Value::ToUniquePtrValue(utterance->GetOptions()->Clone()));
-  if (options->FindKey(constants::kRequiredEventTypesKey))
-    options->RemoveKey(constants::kRequiredEventTypesKey);
-  if (options->FindKey(constants::kDesiredEventTypesKey))
-    options->RemoveKey(constants::kDesiredEventTypesKey);
-  if (sends_end_event && options->FindKey(constants::kEnqueueKey))
-    options->RemoveKey(constants::kEnqueueKey);
-  if (options->FindKey(constants::kSrcIdKey))
-    options->RemoveKey(constants::kSrcIdKey);
-  if (options->FindKey(constants::kIsFinalEventKey))
-    options->RemoveKey(constants::kIsFinalEventKey);
-  if (options->FindKey(constants::kOnEventKey))
-    options->RemoveKey(constants::kOnEventKey);
+  base::Value::Dict options = utterance->GetOptions()->GetDict().Clone();
+  options.Remove(constants::kRequiredEventTypesKey);
+  options.Remove(constants::kDesiredEventTypesKey);
+  if (sends_end_event)
+    options.Remove(constants::kEnqueueKey);
+  options.Remove(constants::kSrcIdKey);
+  options.Remove(constants::kIsFinalEventKey);
+  options.Remove(constants::kOnEventKey);
 
   // Get the volume, pitch, and rate, but only if they weren't already in
   // the options. TODO(dmazzoni): these shouldn't be redundant.
   // http://crbug.com/463264
-  if (!options->FindKey(constants::kRateKey)) {
-    options->SetDoubleKey(constants::kRateKey,
-                          utterance->GetContinuousParameters().rate);
+  if (!options.Find(constants::kRateKey)) {
+    options.Set(constants::kRateKey, utterance->GetContinuousParameters().rate);
   }
-  if (!options->FindKey(constants::kPitchKey)) {
-    options->SetDoubleKey(constants::kPitchKey,
-                          utterance->GetContinuousParameters().pitch);
+  if (!options.Find(constants::kPitchKey)) {
+    options.Set(constants::kPitchKey,
+                utterance->GetContinuousParameters().pitch);
   }
-  if (!options->FindKey(constants::kVolumeKey)) {
-    options->SetDoubleKey(constants::kVolumeKey,
-                          utterance->GetContinuousParameters().volume);
+  if (!options.Find(constants::kVolumeKey)) {
+    options.Set(constants::kVolumeKey,
+                utterance->GetContinuousParameters().volume);
   }
 
   // Add the voice name and language to the options if they're not
   // already there, since they might have been picked by the TTS controller
   // rather than directly by the client that requested the speech.
-  if (!options->FindKey(constants::kVoiceNameKey))
-    options->SetString(constants::kVoiceNameKey, voice.name);
-  if (!options->FindKey(constants::kLangKey))
-    options->SetString(constants::kLangKey, voice.lang);
+  if (!options.Find(constants::kVoiceNameKey))
+    options.Set(constants::kVoiceNameKey, voice.name);
+  if (!options.Find(constants::kLangKey))
+    options.Set(constants::kLangKey, voice.lang);
 
-  args->Append(std::move(options));
-  args->Append(utterance->GetId());
+  args->GetList().Append(std::move(options));
+  args->GetList().Append(utterance->GetId());
   return args;
 }
 
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.cc b/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.cc
index 56c4e21c..4ac5e1a 100644
--- a/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.cc
+++ b/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.cc
@@ -226,12 +226,12 @@
 
   // Add audio stream options.
   DCHECK(audio_parameters_);
-  auto audio_stream_options = std::make_unique<base::DictionaryValue>();
-  audio_stream_options->SetInteger(tts_extension_api_constants::kSampleRateKey,
-                                   audio_parameters_->sample_rate);
-  audio_stream_options->SetInteger(tts_extension_api_constants::kBufferSizeKey,
-                                   audio_parameters_->buffer_size);
-  args->Append(std::move(audio_stream_options));
+  base::Value::Dict audio_stream_options;
+  audio_stream_options.Set(tts_extension_api_constants::kSampleRateKey,
+                           audio_parameters_->sample_rate);
+  audio_stream_options.Set(tts_extension_api_constants::kBufferSizeKey,
+                           audio_parameters_->buffer_size);
+  args->GetList().Append(std::move(audio_stream_options));
 
   // Disconnect any previous receivers.
   tts_event_observer_receiver_set_.Clear();
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index d9676a0c..25d4bb8 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -193,8 +193,9 @@
     "toolbar/chrome_labs_prefs.h",
     "toolbar/chrome_location_bar_model_delegate.cc",
     "toolbar/chrome_location_bar_model_delegate.h",
-    "translate/partial_translate_bubble_model.cc",
     "translate/partial_translate_bubble_model.h",
+    "translate/partial_translate_bubble_model_impl.cc",
+    "translate/partial_translate_bubble_model_impl.h",
     "translate/source_language_combobox_model.cc",
     "translate/source_language_combobox_model.h",
     "translate/target_language_combobox_model.cc",
diff --git a/chrome/browser/ui/ash/projector/pending_screencast_manager.cc b/chrome/browser/ui/ash/projector/pending_screencast_manager.cc
index 59497dc1..b84325a 100644
--- a/chrome/browser/ui/ash/projector/pending_screencast_manager.cc
+++ b/chrome/browser/ui/ash/projector/pending_screencast_manager.cc
@@ -17,7 +17,6 @@
 #include "base/task/bind_post_task.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
-#include "base/time/time.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
@@ -211,6 +210,7 @@
     // Since DriveFS is unmounted, screencasts stop uploading. Notifies pending
     // screencast status has changed.
     pending_screencast_change_callback_.Run(pending_screencast_cache_);
+    last_pending_screencast_change_tick_ = base::TimeTicks();
   }
   error_syncing_files_.clear();
 }
@@ -297,8 +297,8 @@
 void PendingScreencastManager::OnProcessAndGenerateNewScreencastsFinished(
     const base::TimeTicks task_start_tick,
     const ash::PendingScreencastSet& screencasts) {
-  ash::RecordPendingScreencastBatchIOTaskDuration(base::TimeTicks::Now() -
-                                                  task_start_tick);
+  const base::TimeTicks now = base::TimeTicks::Now();
+  ash::RecordPendingScreencastBatchIOTaskDuration(now - task_start_tick);
 
   // Returns if pending screencasts didn't change.
   if (screencasts == pending_screencast_cache_)
@@ -307,6 +307,14 @@
 
   // Notifies pending screencast status changed.
   pending_screencast_change_callback_.Run(pending_screencast_cache_);
+  if (!last_pending_screencast_change_tick_.is_null()) {
+    ash::RecordPendingScreencastChangeInterval(
+        now - last_pending_screencast_change_tick_);
+  }
+  // Resets `last_pending_screencast_change_tick_` to null. We don't track time
+  // delta between finish uploading and new uploading started.
+  last_pending_screencast_change_tick_ =
+      pending_screencast_cache_.empty() ? base::TimeTicks() : now;
 }
 
 void PendingScreencastManager::OnUserProfileLoaded(
diff --git a/chrome/browser/ui/ash/projector/pending_screencast_manager.h b/chrome/browser/ui/ash/projector/pending_screencast_manager.h
index 109713c..e646660b 100644
--- a/chrome/browser/ui/ash/projector/pending_screencast_manager.h
+++ b/chrome/browser/ui/ash/projector/pending_screencast_manager.h
@@ -13,6 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/scoped_observation.h"
+#include "base/time/time.h"
 #include "components/session_manager/core/session_manager.h"
 #include "components/session_manager/core/session_manager_observer.h"
 #include "components/user_manager/user_manager.h"
@@ -26,7 +27,6 @@
 
 namespace base {
 class FilePath;
-class TimeTicks;
 }
 
 // A callback to notify the change of pending screencasts to
@@ -48,6 +48,9 @@
   ~PendingScreencastManager() override;
 
   // Test only:
+  base::TimeTicks last_pending_screencast_change_tick() const {
+    return last_pending_screencast_change_tick_;
+  }
   bool IsDriveFsObservationObservingSource(drivefs::DriveFsHost* source) const;
 
   // drivefs::DriveFsHostObserver:
@@ -102,6 +105,12 @@
       &user_manager::UserManager::RemoveSessionStateObserver>
       session_state_observation_{this};
 
+  // The time tick when last `pending_screencast_change_callback_` was called.
+  // Could be null if last `pending_screencast_change_callback_` was called with
+  // empty screencasts set or no `pending_screencast_change_callback_` invoked
+  // in the current ChromeOS session.
+  base::TimeTicks last_pending_screencast_change_tick_;
+
   base::WeakPtrFactory<PendingScreencastManager> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/ui/ash/projector/pending_screencast_manager_browsertest.cc b/chrome/browser/ui/ash/projector/pending_screencast_manager_browsertest.cc
index cdf323c3..0e7dff81 100644
--- a/chrome/browser/ui/ash/projector/pending_screencast_manager_browsertest.cc
+++ b/chrome/browser/ui/ash/projector/pending_screencast_manager_browsertest.cc
@@ -15,6 +15,7 @@
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/ash/drive/drivefs_test_support.h"
 #include "chrome/browser/ash/file_manager/fileapi_util.h"
@@ -43,8 +44,9 @@
 
 constexpr char kProjectorPendingScreencastBatchIOTaskDurationHistogramName[] =
     "Ash.Projector.PendingScreencastBatchIOTaskDuration";
+constexpr char kProjectorPendingScreencastChangeIntervalHistogramName[] =
+    "Ash.Projector.PendingScreencastChangeInterval";
 
-// constexpr char kTestDataToWrite[] = "Data size of 16.";
 // The test media file is 0.7 mb.
 constexpr int64_t kTestMediaFileBytes = 700 * 1024;
 // The test metadata file is 0.1 mb.
@@ -210,6 +212,12 @@
   EXPECT_CALL(*this, PendingScreencastChangeCallback(testing::_)).Times(1);
   pending_screencast_manager()->OnSyncingStatusUpdate(syncing_status);
   content::RunAllTasksUntilIdle();
+  histogram_tester_.ExpectTotalCount(
+      kProjectorPendingScreencastChangeIntervalHistogramName,
+      /*count=*/0);
+  const base::TimeTicks last_pending_screencast_change_tick =
+      pending_screencast_manager()->last_pending_screencast_change_tick();
+  EXPECT_NE(base::TimeTicks(), last_pending_screencast_change_tick);
 
   const PendingScreencastSet pending_screencasts =
       pending_screencast_manager()->GetPendingScreencasts();
@@ -225,6 +233,14 @@
   pending_screencast_manager()->OnSyncingStatusUpdate(syncing_status);
   content::RunAllTasksUntilIdle();
 
+  // Expects no report since PendingScreencastChangeCallback wasn't invoked.
+  histogram_tester_.ExpectTotalCount(
+      kProjectorPendingScreencastChangeIntervalHistogramName,
+      /*count=*/0);
+  EXPECT_EQ(
+      last_pending_screencast_change_tick,
+      pending_screencast_manager()->last_pending_screencast_change_tick());
+
   // Tests PendingScreencastChangeCallback will be invoked if pending
   // screencast status changes.
   EXPECT_CALL(*this, PendingScreencastChangeCallback(testing::_)).Times(1);
@@ -232,6 +248,25 @@
   pending_screencast_manager()->OnSyncingStatusUpdate(syncing_status);
   content::RunAllTasksUntilIdle();
 
+  // Since pending screencast set is empty, the last pending screencast change
+  // tick is reset to null:
+  EXPECT_EQ(
+      base::TimeTicks(),
+      pending_screencast_manager()->last_pending_screencast_change_tick());
+
+  const base::TimeDelta elapsed_time =
+      base::TimeTicks::Now() - last_pending_screencast_change_tick;
+  auto change_interval_samples = histogram_tester_.GetAllSamples(
+      kProjectorPendingScreencastChangeIntervalHistogramName);
+  // Expects only 1 sample.
+  EXPECT_EQ(1u, change_interval_samples.size());
+  // Expects the sample only have 1 count.
+  EXPECT_EQ(1, change_interval_samples.front().count);
+  // Since the end of `elapsed_time` is gotten from "base::TimeTicks::Now()"
+  // after PendingScreencastChangeCallback gets invoked. Expects `elapsed_time`
+  // is greater than the sample.
+  EXPECT_GT(elapsed_time.InMicroseconds(), change_interval_samples.front().min);
+
   histogram_tester_.ExpectTotalCount(
       kProjectorPendingScreencastBatchIOTaskDurationHistogramName,
       /*count=*/3);
diff --git a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc
index 48982bf..2737a8ff 100644
--- a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc
+++ b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.cc
@@ -29,8 +29,6 @@
 #include "components/send_tab_to_self/target_device_info.h"
 #include "components/signin/public/base/consent_level.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
@@ -126,22 +124,18 @@
   SendTabToSelfModel* model =
       SendTabToSelfSyncServiceFactory::GetForProfile(GetProfile())
           ->GetSendTabToSelfModel();
-  content::NavigationEntry* navigation_entry =
-      GetWebContents().GetController().GetLastCommittedEntry();
   // TODO(crbug.com/1288843): This duplicates the ShouldOfferFeature() check,
   // instead the 2 codepaths should share code.
-  DCHECK(navigation_entry);
+  const GURL& shared_url = GetWebContents().GetLastCommittedURL();
   if (!model->IsReady()) {
     // TODO(https://crbug.com/1280681): Is this legit? In STTSv2, there may not
     // *be* a DesktopNotificationHandler for profile, and we're violating the
     // lifetime rules of DesktopNotificationHandler here I think.
-    DesktopNotificationHandler(GetProfile())
-        .DisplayFailureMessage(navigation_entry->GetURL());
+    DesktopNotificationHandler(GetProfile()).DisplayFailureMessage(shared_url);
     return;
   }
 
-  model->AddEntry(navigation_entry->GetURL(),
-                  base::UTF16ToUTF8(navigation_entry->GetTitle()),
+  model->AddEntry(shared_url, base::UTF16ToUTF8(GetWebContents().GetTitle()),
                   target_device_guid);
   // Show confirmation message.
   show_message_ = true;
diff --git a/chrome/browser/ui/translate/partial_translate_bubble_model.h b/chrome/browser/ui/translate/partial_translate_bubble_model.h
index 24d29bb..317f063 100644
--- a/chrome/browser/ui/translate/partial_translate_bubble_model.h
+++ b/chrome/browser/ui/translate/partial_translate_bubble_model.h
@@ -42,53 +42,39 @@
     VIEW_STATE_TARGET_LANGUAGE
   };
 
-  PartialTranslateBubbleModel(
-      ViewState view_state,
-      std::unique_ptr<translate::TranslateUIDelegate> ui_delegate);
-
-  PartialTranslateBubbleModel(const PartialTranslateBubbleModel&) = delete;
-  PartialTranslateBubbleModel& operator=(const PartialTranslateBubbleModel&) =
-      delete;
-
-  ~PartialTranslateBubbleModel() override;
+  ~PartialTranslateBubbleModel() override = default;
 
   // Returns the current view state.
-  ViewState GetViewState() const;
+  virtual ViewState GetViewState() const = 0;
 
   // Transitions the view state.
-  void SetViewState(ViewState view_state);
+  virtual void SetViewState(ViewState view_state) = 0;
 
   // Shows an error.
-  void ShowError(translate::TranslateErrors::Type error_type);
+  virtual void ShowError(translate::TranslateErrors::Type error_type) = 0;
 
   // Goes back from the 'Advanced' view state.
-  void GoBackFromAdvanced();
+  virtual void GoBackFromAdvanced() = 0;
 
   // TranslateLanguageListModel:
-  int GetNumberOfSourceLanguages() const override;
-  int GetNumberOfTargetLanguages() const override;
-  std::u16string GetSourceLanguageNameAt(int index) const override;
-  std::u16string GetTargetLanguageNameAt(int index) const override;
-  int GetSourceLanguageIndex() const override;
-  void UpdateSourceLanguageIndex(int index) override;
-  int GetTargetLanguageIndex() const override;
-  void UpdateTargetLanguageIndex(int index) override;
+  int GetNumberOfSourceLanguages() const override = 0;
+  int GetNumberOfTargetLanguages() const override = 0;
+  std::u16string GetSourceLanguageNameAt(int index) const override = 0;
+  std::u16string GetTargetLanguageNameAt(int index) const override = 0;
+  int GetSourceLanguageIndex() const override = 0;
+  void UpdateSourceLanguageIndex(int index) override = 0;
+  int GetTargetLanguageIndex() const override = 0;
+  void UpdateTargetLanguageIndex(int index) override = 0;
 
   // Starts translating the selected text.
-  void Translate();
+  virtual void Translate() = 0;
 
   // Reverts translation.
-  void RevertTranslation();
+  virtual void RevertTranslation() = 0;
 
   // Returns true if the current text selection is translated in the currently
   // selected source and target language.
-  bool IsCurrentSelectionTranslated() const;
-
- private:
-  std::unique_ptr<translate::TranslateUIDelegate> ui_delegate_;
-
-  // The current view type.
-  ViewState current_view_state_;
+  virtual bool IsCurrentSelectionTranslated() const = 0;
 };
 
 #endif  // CHROME_BROWSER_UI_TRANSLATE_PARTIAL_TRANSLATE_BUBBLE_MODEL_H_
diff --git a/chrome/browser/ui/translate/partial_translate_bubble_model.cc b/chrome/browser/ui/translate/partial_translate_bubble_model_impl.cc
similarity index 71%
rename from chrome/browser/ui/translate/partial_translate_bubble_model.cc
rename to chrome/browser/ui/translate/partial_translate_bubble_model_impl.cc
index 9c5762e..ed81b010 100644
--- a/chrome/browser/ui/translate/partial_translate_bubble_model.cc
+++ b/chrome/browser/ui/translate/partial_translate_bubble_model_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/translate/partial_translate_bubble_model.h"
+#include "chrome/browser/ui/translate/partial_translate_bubble_model_impl.h"
 
 #include <utility>
 
@@ -14,7 +14,7 @@
 // replace and take the role of the TranslateUIDelegate. TranslateUIDelegate
 // calls have been left in this implementation as future reference for
 // implementing PartialTranslateManager.
-PartialTranslateBubbleModel::PartialTranslateBubbleModel(
+PartialTranslateBubbleModelImpl::PartialTranslateBubbleModelImpl(
     ViewState view_state,
     std::unique_ptr<translate::TranslateUIDelegate> ui_delegate)
     : ui_delegate_(std::move(ui_delegate)) {
@@ -23,76 +23,76 @@
   current_view_state_ = view_state;
 }
 
-PartialTranslateBubbleModel::~PartialTranslateBubbleModel() = default;
+PartialTranslateBubbleModelImpl::~PartialTranslateBubbleModelImpl() = default;
 
-PartialTranslateBubbleModel::ViewState
-PartialTranslateBubbleModel::GetViewState() const {
+PartialTranslateBubbleModelImpl::ViewState
+PartialTranslateBubbleModelImpl::GetViewState() const {
   return current_view_state_;
 }
 
-void PartialTranslateBubbleModel::SetViewState(
-    PartialTranslateBubbleModel::ViewState view_state) {
+void PartialTranslateBubbleModelImpl::SetViewState(
+    PartialTranslateBubbleModelImpl::ViewState view_state) {
   current_view_state_ = view_state;
 }
 
-void PartialTranslateBubbleModel::ShowError(
+void PartialTranslateBubbleModelImpl::ShowError(
     translate::TranslateErrors::Type error_type) {
   // TODO(crbug/1314825): implement when partial translate specific
   // metrics are added.
 }
 
-int PartialTranslateBubbleModel::GetNumberOfSourceLanguages() const {
+int PartialTranslateBubbleModelImpl::GetNumberOfSourceLanguages() const {
   return ui_delegate_->GetNumberOfLanguages();
 }
 
-int PartialTranslateBubbleModel::GetNumberOfTargetLanguages() const {
+int PartialTranslateBubbleModelImpl::GetNumberOfTargetLanguages() const {
   // Subtract 1 to account for unknown language option being omitted.
   return ui_delegate_->GetNumberOfLanguages() - 1;
 }
 
-std::u16string PartialTranslateBubbleModel::GetSourceLanguageNameAt(
+std::u16string PartialTranslateBubbleModelImpl::GetSourceLanguageNameAt(
     int index) const {
   return ui_delegate_->GetLanguageNameAt(index);
 }
 
-std::u16string PartialTranslateBubbleModel::GetTargetLanguageNameAt(
+std::u16string PartialTranslateBubbleModelImpl::GetTargetLanguageNameAt(
     int index) const {
   // Add 1 to account for unknown language option at index 0 in
   // TranslateUIDelegate language list.
   return ui_delegate_->GetLanguageNameAt(index + 1);
 }
 
-int PartialTranslateBubbleModel::GetSourceLanguageIndex() const {
+int PartialTranslateBubbleModelImpl::GetSourceLanguageIndex() const {
   return ui_delegate_->GetSourceLanguageIndex();
 }
 
-void PartialTranslateBubbleModel::UpdateSourceLanguageIndex(int index) {
+void PartialTranslateBubbleModelImpl::UpdateSourceLanguageIndex(int index) {
   ui_delegate_->UpdateSourceLanguageIndex(index);
 }
 
-int PartialTranslateBubbleModel::GetTargetLanguageIndex() const {
+int PartialTranslateBubbleModelImpl::GetTargetLanguageIndex() const {
   // Subtract 1 to account for unknown language option being omitted from the
   // bubble target language list.
   return ui_delegate_->GetTargetLanguageIndex() - 1;
 }
 
-void PartialTranslateBubbleModel::UpdateTargetLanguageIndex(int index) {
+void PartialTranslateBubbleModelImpl::UpdateTargetLanguageIndex(int index) {
   // Add 1 to account for unknown language option at index 0 in
   // TranslateUIDelegate language list.
   ui_delegate_->UpdateTargetLanguageIndex(index + 1);
 }
 
-void PartialTranslateBubbleModel::Translate() {
+void PartialTranslateBubbleModelImpl::Translate() {
   // TODO(crbug/1314825): Update implementation when PartialTranslateManager is
   // complete.
 }
 
-void PartialTranslateBubbleModel::RevertTranslation() {
+void PartialTranslateBubbleModelImpl::RevertTranslation() {
   // TODO(crbug/1314825): Update implementation when PartialTranslateManager is
   // complete.
 }
 
-bool PartialTranslateBubbleModel::IsCurrentSelectionTranslated() const {
+bool PartialTranslateBubbleModelImpl::IsCurrentSelectionTranslated() const {
   // TODO(crbug/1314825): Update implementation when PartialTranslateManager is
   // complete.
 
diff --git a/chrome/browser/ui/translate/partial_translate_bubble_model_impl.h b/chrome/browser/ui/translate/partial_translate_bubble_model_impl.h
new file mode 100644
index 0000000..2d38ccf0
--- /dev/null
+++ b/chrome/browser/ui/translate/partial_translate_bubble_model_impl.h
@@ -0,0 +1,46 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_TRANSLATE_PARTIAL_TRANSLATE_BUBBLE_MODEL_IMPL_H_
+#define CHROME_BROWSER_UI_TRANSLATE_PARTIAL_TRANSLATE_BUBBLE_MODEL_IMPL_H_
+
+#include "chrome/browser/ui/translate/partial_translate_bubble_model.h"
+
+class PartialTranslateBubbleModelImpl : public PartialTranslateBubbleModel {
+ public:
+  PartialTranslateBubbleModelImpl(
+      ViewState view_state,
+      std::unique_ptr<translate::TranslateUIDelegate> ui_delegate);
+
+  PartialTranslateBubbleModelImpl(const PartialTranslateBubbleModelImpl&) =
+      delete;
+  PartialTranslateBubbleModelImpl& operator=(
+      const PartialTranslateBubbleModelImpl&) = delete;
+
+  ~PartialTranslateBubbleModelImpl() override;
+
+  // PartialTranslateBubbleModel methods:
+  ViewState GetViewState() const override;
+  void SetViewState(ViewState view_state) override;
+  void ShowError(translate::TranslateErrors::Type error_type) override;
+  int GetNumberOfSourceLanguages() const override;
+  int GetNumberOfTargetLanguages() const override;
+  std::u16string GetSourceLanguageNameAt(int index) const override;
+  std::u16string GetTargetLanguageNameAt(int index) const override;
+  int GetSourceLanguageIndex() const override;
+  void UpdateSourceLanguageIndex(int index) override;
+  int GetTargetLanguageIndex() const override;
+  void UpdateTargetLanguageIndex(int index) override;
+  void Translate() override;
+  void RevertTranslation() override;
+  bool IsCurrentSelectionTranslated() const override;
+
+ private:
+  std::unique_ptr<translate::TranslateUIDelegate> ui_delegate_;
+
+  // The current view type.
+  ViewState current_view_state_;
+};
+
+#endif  // CHROME_BROWSER_UI_TRANSLATE_PARTIAL_TRANSLATE_BUBBLE_MODEL_IMPL_H_
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
index fd7d76b9..e42887f 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
@@ -415,13 +415,14 @@
   EXPECT_TRUE(menu->GetMenuItemByID(IDC_BOOKMARK_BAR_NEW_FOLDER)->GetVisible());
 
   // Now set the managed bookmarks policy.
-  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
-  dict->SetStringKey("name", "Google");
-  dict->SetStringKey("url", "http://google.com");
-  base::ListValue list;
+  base::Value::Dict dict;
+  dict.Set("name", "Google");
+  dict.Set("url", "http://google.com");
+  base::Value::List list;
   list.Append(std::move(dict));
   EXPECT_TRUE(managed->managed_node()->children().empty());
-  profile_->GetPrefs()->Set(bookmarks::prefs::kManagedBookmarks, list);
+  profile_->GetPrefs()->Set(bookmarks::prefs::kManagedBookmarks,
+                            base::Value(std::move(list)));
   EXPECT_FALSE(managed->managed_node()->children().empty());
 
   // New context menus now show the "Show managed bookmarks" option.
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_dialog_browsertest.cc b/chrome/browser/ui/views/download/bubble/download_bubble_dialog_browsertest.cc
new file mode 100644
index 0000000..88968dc
--- /dev/null
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_dialog_browsertest.cc
@@ -0,0 +1,278 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/download/bubble/download_toolbar_button_view.h"
+
+#include <memory>
+#include "base/containers/fixed_flat_map.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/browser/ui/views/download/bubble/download_bubble_row_list_view.h"
+#include "chrome/browser/ui/views/download/bubble/download_bubble_row_view.h"
+#include "chrome/browser/ui/views/download/bubble/download_toolbar_button_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/safe_browsing/core/common/features.h"
+#include "content/public/browser/download_manager.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/download_test_observer.h"
+#include "content/public/test/slow_download_http_response.h"
+#include "ui/events/test/event_generator.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/widget/widget_utils.h"
+#include "url/gurl.h"
+
+namespace {
+enum Testcase {
+  kInProgressDownload,
+  kCompletedDownload,
+  kFullView,
+  kDangerousDownloadSubpage
+};
+
+auto kNameToTestcase = base::MakeFixedFlatMap<std::string, Testcase>({
+    {"InProgressDownload", kInProgressDownload},
+    {"CompletedDownload", kCompletedDownload},
+    {"FullView", kFullView},
+    {"DangerousDownloadSubpage", kDangerousDownloadSubpage},
+});
+
+constexpr base::StringPiece kDangerousUrl =
+    "/downloads/dangerous/dangerous.swf";
+}  // namespace
+
+class DownloadBubbleDialogBrowserTest : public DialogBrowserTest {
+ public:
+  DownloadBubbleDialogBrowserTest() {
+    feature_list_.InitWithFeatures(
+        /*enabled_features=*/{safe_browsing::kDownloadBubble},
+        /*disabled_features=*/{});
+  }
+  DownloadBubbleDialogBrowserTest(const DownloadBubbleDialogBrowserTest& test) =
+      delete;
+  DownloadBubbleDialogBrowserTest& operator=(
+      const DownloadBubbleDialogBrowserTest& test) = delete;
+
+  DownloadToolbarButtonView* GetDownloadToolbarButtonView() {
+    BrowserView* browser_view =
+        BrowserView::GetBrowserViewForBrowser(browser());
+    return (browser_view && browser_view->toolbar())
+               ? browser_view->toolbar()->download_button()
+               : nullptr;
+  }
+
+  void ClickDownloadItem() {
+    DownloadToolbarButtonView* button = GetDownloadToolbarButtonView();
+    const views::View::Views& row_list =
+        button->download_row_list_view_->children();
+    ASSERT_EQ(row_list.size(), 1u);
+    DownloadBubbleRowView* row =
+        static_cast<DownloadBubbleRowView*>(row_list[0]);
+
+    base::RunLoop dangerous_wait;
+    row->SetNotifyDangerousDownloadCallbackForTesting(
+        dangerous_wait.QuitClosure());
+    dangerous_wait.Run();
+
+    ui::test::EventGenerator generator(
+        GetRootWindow(button->bubble_delegate_->GetWidget()));
+    generator.MoveMouseTo(row->GetBoundsInScreen().CenterPoint());
+    generator.ClickLeftButton();
+  }
+
+  void ClickDownloadToolbarButton(bool is_creation) {
+    DownloadToolbarButtonView* button = GetDownloadToolbarButtonView();
+    base::RunLoop wait;
+    if (is_creation) {
+      button->SetBubbleCreatedCallbackForTesting(wait.QuitClosure());
+    } else {
+      button->SetBubbleDestroyedCallbackForTesting(wait.QuitClosure());
+    }
+
+    ui::test::EventGenerator generator(GetRootWindow(button->GetWidget()));
+    generator.MoveMouseTo(button->GetBoundsInScreen().CenterPoint());
+    generator.ClickLeftButton();
+    wait.Run();
+  }
+
+  content::DownloadManager::DownloadVector GetDownloadItems() {
+    content::DownloadManager::DownloadVector items;
+    browser()->profile()->GetDownloadManager()->GetAllDownloads(&items);
+    return items;
+  }
+
+  void StartServer() {
+    embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
+        &content::SlowDownloadHttpResponse::HandleSlowDownloadRequest));
+    base::FilePath test_file_directory;
+    base::PathService::Get(chrome::DIR_TEST_DATA, &test_file_directory);
+    embedded_test_server()->ServeFilesFromDirectory(test_file_directory);
+    ASSERT_TRUE(embedded_test_server()->Start());
+  }
+
+  void StartDownload(base::StringPiece url, bool observe_terminally) {
+    std::unique_ptr<content::DownloadTestObserver> observer;
+    if (observe_terminally) {
+      observer = std::make_unique<content::DownloadTestObserverTerminal>(
+          browser()->profile()->GetDownloadManager(), 1,
+          content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_QUIT);
+    } else {
+      observer = std::make_unique<content::DownloadTestObserverInProgress>(
+          browser()->profile()->GetDownloadManager(), 1);
+    }
+
+    ui_test_utils::NavigateToURLWithDisposition(
+        browser(), embedded_test_server()->GetURL(url),
+        WindowOpenDisposition::NEW_FOREGROUND_TAB,
+        ui_test_utils::BROWSER_TEST_NONE);
+    observer->WaitForFinished();
+  }
+
+  void WaitForBubbleCreation() {
+    // Download Toolbar button should exist.
+    ASSERT_NE(GetDownloadToolbarButtonView(), nullptr);
+    base::RunLoop creation_wait;
+    GetDownloadToolbarButtonView()->SetBubbleCreatedCallbackForTesting(
+        creation_wait.QuitClosure());
+    creation_wait.Run();
+  }
+
+  void CompleteSlowDownload() {
+    content::DownloadTestObserverTerminal observer(
+        browser()->profile()->GetDownloadManager(), 1,
+        content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_QUIT);
+    ui_test_utils::NavigateToURLWithDisposition(
+        browser(),
+        embedded_test_server()->GetURL(
+            content::SlowHttpResponse::kFinishSlowResponseUrl),
+        WindowOpenDisposition::NEW_FOREGROUND_TAB,
+        ui_test_utils::BROWSER_TEST_NONE);
+    observer.WaitForFinished();
+  }
+
+  void SetUp() override {
+    StartServer();
+    InProcessBrowserTest::SetUp();
+  }
+
+  // DialogBrowserTest:
+  void ShowUi(const std::string& name) override {
+    content::DownloadManager::DownloadVector items;
+
+    auto* testcase_iter = kNameToTestcase.find(name);
+    ASSERT_TRUE(testcase_iter != kNameToTestcase.end());
+    testcase_ = testcase_iter->second;
+    switch (testcase_) {
+      case Testcase::kInProgressDownload:
+        StartDownload(content::SlowDownloadHttpResponse::kKnownSizeUrl,
+                      /*observe_terminally=*/false);
+        WaitForBubbleCreation();
+        break;
+      case Testcase::kCompletedDownload:
+        StartDownload(content::SlowDownloadHttpResponse::kKnownSizeUrl,
+                      /*observe_terminally=*/false);
+        WaitForBubbleCreation();
+        EXPECT_TRUE(GetDownloadToolbarButtonView()->IsBubbleVisible());
+        ClickDownloadToolbarButton(/*is_creation=*/false);
+        EXPECT_FALSE(GetDownloadToolbarButtonView()->IsBubbleVisible());
+        items = GetDownloadItems();
+        ASSERT_EQ(items.size(), 1u);
+        EXPECT_EQ(items[0]->GetState(), download::DownloadItem::IN_PROGRESS);
+        CompleteSlowDownload();
+        WaitForBubbleCreation();
+        break;
+      case Testcase::kFullView:
+        StartDownload(content::SlowDownloadHttpResponse::kKnownSizeUrl,
+                      /*observe_terminally=*/false);
+        CompleteSlowDownload();
+        WaitForBubbleCreation();
+        EXPECT_TRUE(GetDownloadToolbarButtonView()->IsBubbleVisible());
+        ClickDownloadToolbarButton(/*is_creation=*/false);
+        EXPECT_FALSE(GetDownloadToolbarButtonView()->IsBubbleVisible());
+        ClickDownloadToolbarButton(/*is_creation=*/true);
+        break;
+      case Testcase::kDangerousDownloadSubpage:
+        StartDownload(kDangerousUrl, /*observe_terminally=*/true);
+        WaitForBubbleCreation();
+        ClickDownloadItem();
+        break;
+    }
+  }
+
+  bool VerifyUi() override {
+    if (!DialogBrowserTest::VerifyUi())
+      return false;
+    DownloadToolbarButtonView* button = GetDownloadToolbarButtonView();
+    content::DownloadManager::DownloadVector items = GetDownloadItems();
+    if (items.size() != 1u) {
+      LOG(ERROR) << "There should be only one download item, not "
+                 << items.size();
+      return false;
+    }
+    switch (testcase_) {
+      case Testcase::kInProgressDownload:
+        EXPECT_TRUE(button->IsBubbleVisible());
+        EXPECT_TRUE(button->is_primary_partial_view_);
+        EXPECT_FALSE(button->security_view_->GetVisible());
+        EXPECT_EQ(button->download_list_size_, 1u);
+        EXPECT_EQ(items[0]->GetState(), download::DownloadItem::IN_PROGRESS);
+        items[0]->Cancel(true);
+        return true;
+      case Testcase::kCompletedDownload:
+        EXPECT_TRUE(button->IsBubbleVisible());
+        EXPECT_TRUE(button->is_primary_partial_view_);
+        EXPECT_FALSE(button->security_view_->GetVisible());
+        EXPECT_EQ(button->download_list_size_, 1u);
+        EXPECT_EQ(items[0]->GetState(), download::DownloadItem::COMPLETE);
+        return true;
+      case Testcase::kFullView:
+        EXPECT_TRUE(button->IsBubbleVisible());
+        EXPECT_FALSE(button->is_primary_partial_view_);
+        EXPECT_FALSE(button->security_view_->GetVisible());
+        EXPECT_EQ(button->download_list_size_, 1u);
+        EXPECT_EQ(items[0]->GetState(), download::DownloadItem::COMPLETE);
+        return true;
+      case Testcase::kDangerousDownloadSubpage:
+        EXPECT_TRUE(button->IsBubbleVisible());
+        EXPECT_TRUE(button->is_primary_partial_view_);
+        EXPECT_TRUE(button->security_view_->GetVisible());
+        EXPECT_EQ(button->download_list_size_, 1u);
+        items[0]->Cancel(true);
+        return true;
+    }
+    return false;
+  }
+
+  void TearDown() override {
+    ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+    InProcessBrowserTest::TearDown();
+  }
+
+ private:
+  Testcase testcase_;
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(DownloadBubbleDialogBrowserTest,
+                       InvokeUi_InProgressDownload) {
+  ShowAndVerifyUi();
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadBubbleDialogBrowserTest,
+                       InvokeUi_CompletedDownload) {
+  ShowAndVerifyUi();
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadBubbleDialogBrowserTest, InvokeUi_FullView) {
+  ShowAndVerifyUi();
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadBubbleDialogBrowserTest,
+                       InvokeUi_DangerousDownloadSubpage) {
+  ShowAndVerifyUi();
+}
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
index 9468597..43f3982f 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
@@ -389,6 +389,8 @@
   LoadIcon();
   UpdateButtonsForItems();
   UpdateProgressBar();
+  ui_updated_for_dangerous_download_ = model_->IsDangerous();
+  NotifyIfDownloadDangerous();
 }
 
 void DownloadBubbleRowView::OnDownloadOpened() {
@@ -445,5 +447,18 @@
                      base::RepeatingClosure());
 }
 
+void DownloadBubbleRowView::SetNotifyDangerousDownloadCallbackForTesting(
+    base::OnceClosure callback) {
+  notify_dangerous_download_callback_for_testing_ = std::move(callback);
+  NotifyIfDownloadDangerous();
+}
+
+void DownloadBubbleRowView::NotifyIfDownloadDangerous() {
+  if (ui_updated_for_dangerous_download_ &&
+      notify_dangerous_download_callback_for_testing_) {
+    std::move(notify_dangerous_download_callback_for_testing_).Run();
+  }
+}
+
 BEGIN_METADATA(DownloadBubbleRowView, views::View)
 END_METADATA
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h
index 0456a15..ddd68d33 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h
@@ -69,6 +69,8 @@
                                   float new_device_scale_factor) override;
 
  private:
+  friend class DownloadBubbleDialogBrowserTest;
+
   raw_ptr<views::MdTextButton> AddMainPageButton(
       DownloadCommands::Command command,
       const std::u16string& button_string);
@@ -90,6 +92,12 @@
   void OnDiscardButtonPressed();
   void OnMainButtonPressed();
 
+  // Callback for dangerous downloads for testing.
+  void SetNotifyDangerousDownloadCallbackForTesting(base::OnceClosure callback);
+  void NotifyIfDownloadDangerous();
+  base::OnceClosure notify_dangerous_download_callback_for_testing_;
+  bool ui_updated_for_dangerous_download_ = false;
+
   // TODO(bhatiarohit): Add platform-independent icons.
   // The icon for the file. We get platform-specific icons from IconLoader.
   raw_ptr<views::ImageView> icon_ = nullptr;
diff --git a/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc b/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc
index 1298843..ba9f397 100644
--- a/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.cc
@@ -69,6 +69,22 @@
   bubble_controller_.reset();
 }
 
+void DownloadToolbarButtonView::SetBubbleCreatedCallbackForTesting(
+    base::OnceClosure callback) {
+  // The bubble already exists, run the callback right away. This can happen
+  // when starting a new download.
+  if (bubble_delegate_) {
+    std::move(callback).Run();
+    return;
+  }
+  bubble_created_callback_for_testing_ = std::move(callback);
+}
+
+void DownloadToolbarButtonView::SetBubbleDestroyedCallbackForTesting(
+    base::OnceClosure callback) {
+  bubble_destroyed_callback_for_testing_ = std::move(callback);
+}
+
 void DownloadToolbarButtonView::PaintButtonContents(gfx::Canvas* canvas) {
   DownloadDisplayController::ProgressInfo progress_info =
       controller_->GetProgress();
@@ -213,6 +229,11 @@
   bubble_delegate_ = nullptr;
   primary_view_ = nullptr;
   security_view_ = nullptr;
+  download_row_list_view_ = nullptr;
+  download_list_size_ = 0;
+  if (bubble_destroyed_callback_for_testing_) {
+    std::move(bubble_destroyed_callback_for_testing_).Run();
+  }
 }
 
 // TODO(bhatiarohit): Remove the margin around the bubble.
@@ -249,6 +270,9 @@
   bubble_delegate_ = bubble_delegate.get();
   views::BubbleDialogDelegate::CreateBubble(std::move(bubble_delegate));
   bubble_delegate_->GetWidget()->Show();
+  if (bubble_created_callback_for_testing_) {
+    std::move(bubble_created_callback_for_testing_).Run();
+  }
 }
 
 // If the bubble delegate is set (either the main or the partial view), the
@@ -269,17 +293,19 @@
   if (is_primary_partial_view_ && model_list.empty())
     return nullptr;
 
-  auto row_list_view =
-      std::make_unique<DownloadBubbleRowListView>(is_primary_partial_view_);
+  download_list_size_ = model_list.size();
+  auto scroll_view = std::make_unique<views::ScrollView>();
+  download_row_list_view_ = scroll_view->SetContents(
+      std::make_unique<DownloadBubbleRowListView>(is_primary_partial_view_));
   for (DownloadUIModel::DownloadUIModelPtr& model : model_list) {
     // raw pointer is safe as the toolbar owns the bubble, which owns an
     // individual row view.
-    row_list_view->AddChildView(std::make_unique<DownloadBubbleRowView>(
-        std::move(model), row_list_view.get(), bubble_controller_.get(), this));
+    download_row_list_view_->AddChildView(
+        std::make_unique<DownloadBubbleRowView>(
+            std::move(model), download_row_list_view_.get(),
+            bubble_controller_.get(), this));
   }
 
-  auto scroll_view = std::make_unique<views::ScrollView>();
-  scroll_view->SetContents(std::move(row_list_view));
   scroll_view->ClipHeightTo(0, kMaxHeightForRowList);
   scroll_view->SetHorizontalScrollBarMode(
       views::ScrollView::ScrollBarMode::kDisabled);
diff --git a/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.h b/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.h
index 2e92a16..07cbefe 100644
--- a/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.h
+++ b/chrome/browser/ui/views/download/bubble/download_toolbar_button_view.h
@@ -9,6 +9,7 @@
 #include "chrome/browser/download/bubble/download_display.h"
 #include "chrome/browser/download/bubble/download_icon_state.h"
 #include "chrome/browser/download/download_ui_model.h"
+#include "chrome/browser/ui/views/download/bubble/download_bubble_security_view.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/gfx/animation/throb_animation.h"
@@ -19,7 +20,7 @@
 class DownloadDisplayController;
 class DownloadBubbleUIController;
 class DownloadBubbleRowView;
-class DownloadBubbleSecurityView;
+class DownloadBubbleRowListView;
 
 class DownloadBubbleNavigationHandler {
  public:
@@ -67,6 +68,12 @@
   }
 
  private:
+  // For testing.
+  friend class DownloadBubbleDialogBrowserTest;
+  bool IsBubbleVisible() { return bubble_delegate_ != nullptr; }
+  void SetBubbleCreatedCallbackForTesting(base::OnceClosure callback);
+  void SetBubbleDestroyedCallbackForTesting(base::OnceClosure callback);
+
   // views::Button overrides:
   void PaintButtonContents(gfx::Canvas* canvas) override;
 
@@ -90,6 +97,12 @@
   raw_ptr<View> primary_view_ = nullptr;
   raw_ptr<DownloadBubbleSecurityView> security_view_ = nullptr;
 
+  // For testing
+  base::OnceClosure bubble_created_callback_for_testing_;
+  base::OnceClosure bubble_destroyed_callback_for_testing_;
+  size_t download_list_size_ = 0;
+  raw_ptr<DownloadBubbleRowListView> download_row_list_view_ = nullptr;
+
   gfx::SlideAnimation scanning_animation_{this};
 
   base::WeakPtrFactory<DownloadToolbarButtonView> weak_factory_{this};
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 086fe15..8928c56 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -351,7 +351,7 @@
     }
   }
   if (browser_) {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
     params.types_enabled.push_back(PageActionIconType::kSharingHub);
 #else
     if (sharing_hub::SharingHubOmniboxEnabled(profile_) && !is_popup_mode_)
diff --git a/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider.cc b/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider.cc
index a92fd37e..d874ab8c 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_dice_sign_in_provider.cc
@@ -47,7 +47,7 @@
   // sign-in succeeds.
   if (url.is_empty() || url == GURL(url::kAboutBlankURL))
     return false;
-  if (gaia::IsGaiaSignonRealm(url.DeprecatedGetOriginAsURL()))
+  if (gaia::HasGaiaSchemeHostPort(url))
     return false;
   return true;
 }
diff --git a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
index 046d87a..c39dbc27 100644
--- a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
@@ -225,6 +225,7 @@
     // picker.
 
     dialog_builder.OverrideShowCloseButton(false)
+        .AddSeparator()
         .AddCustomField(
             std::make_unique<MenuItemFactory>(
                 l10n_util::GetStringUTF16(
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
index a379b2be..8119dd5 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
@@ -47,6 +47,15 @@
   helper_.CheckPlatformShortcutNotExists(Site::kSiteA);
 }
 
+IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTestMacWinLinux,
+                       CheckDeletePlatformShortcut) {
+  helper_.DeletePlatformShortcut(Site::kSiteA);
+  helper_.InstallCreateShortcutWindowed(Site::kSiteA);
+  helper_.CheckPlatformShortcutAndIcon(Site::kSiteA);
+  helper_.DeletePlatformShortcut(Site::kSiteA);
+  helper_.CheckPlatformShortcutNotExists(Site::kSiteA);
+}
+
 // Generated tests:
 
 IN_PROC_BROWSER_TEST_F(
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
index 4987936..689c8e5 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -301,27 +301,6 @@
   }
   return shortcut_profile;
 }
-
-bool IsShortcutAndIconCorrectOnWin(Profile* profile,
-                                   const std::string& name,
-                                   base::FilePath shortcut_dir,
-                                   SkColor expected_icon_pixel_color) {
-  std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
-  base::FileEnumerator enumerator(shortcut_dir, false,
-                                  base::FileEnumerator::FILES);
-  while (!enumerator.Next().empty()) {
-    std::wstring shortcut_filename = enumerator.GetInfo().GetName().value();
-    if (re2::RE2::FullMatch(converter.to_bytes(shortcut_filename),
-                            name + "(.*).lnk")) {
-      base::FilePath shortcut_path = shortcut_dir.Append(shortcut_filename);
-      if (GetShortcutProfile(shortcut_path) == profile->GetBaseName()) {
-        SkColor icon_pixel_color = GetIconTopLeftColor(shortcut_path);
-        return (icon_pixel_color == expected_icon_pixel_color);
-      }
-    }
-  }
-  return false;
-}
 #endif
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
@@ -1022,6 +1001,86 @@
 #endif
 }
 
+void WebAppIntegrationTestDriver::DeletePlatformShortcut(Site site) {
+  if (!before_state_change_action_state_ && !after_state_change_action_state_)
+    return;
+  BeforeStateChangeAction(__FUNCTION__);
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  AppId app_id = GetAppIdBySiteMode(site);
+  std::string app_name = provider()->registrar().GetAppShortName(app_id);
+  if (app_name.empty()) {
+    ASSERT_TRUE(base::Contains(g_site_to_app_name, site));
+    app_name = g_site_to_app_name.find(site)->second;
+  }
+#if BUILDFLAG(IS_WIN)
+  base::FilePath desktop_shortcut_path =
+      GetShortcutPath(shortcut_override_->desktop.GetPath(), app_name, app_id);
+  ASSERT_TRUE(base::PathExists(desktop_shortcut_path));
+  base::DeleteFile(desktop_shortcut_path);
+  base::FilePath app_menu_shortcut_path = GetShortcutPath(
+      shortcut_override_->application_menu.GetPath(), app_name, app_id);
+  ASSERT_TRUE(base::PathExists(app_menu_shortcut_path));
+  base::DeleteFile(app_menu_shortcut_path);
+  AfterStateChangeAction();
+#elif BUILDFLAG(IS_MAC)
+  base::FilePath app_folder_shortcut_path = GetShortcutPath(
+      shortcut_override_->chrome_apps_folder.GetPath(), app_name, app_id);
+  ASSERT_TRUE(base::PathExists(app_folder_shortcut_path));
+  base::DeleteFile(app_folder_shortcut_path);
+  AfterStateChangeAction();
+#elif BUILDFLAG(IS_LINUX)
+  base::FilePath desktop_shortcut_path =
+      GetShortcutPath(shortcut_override_->desktop.GetPath(), app_name, app_id);
+  ASSERT_TRUE(base::PathExists(desktop_shortcut_path));
+  base::DeleteFile(desktop_shortcut_path);
+  AfterStateChangeAction();
+#else
+  NOTREACHED() << "Not implemented on Chrome OS.";
+#endif
+}
+
+base::FilePath WebAppIntegrationTestDriver::GetShortcutPath(
+    base::FilePath shortcut_dir,
+    const std::string& app_name,
+    const AppId& app_id) {
+  base::FilePath shortcut_path;
+#if BUILDFLAG(IS_WIN)
+  std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
+  base::FileEnumerator enumerator(shortcut_dir, false,
+                                  base::FileEnumerator::FILES);
+  while (!enumerator.Next().empty()) {
+    std::wstring shortcut_filename = enumerator.GetInfo().GetName().value();
+    if (re2::RE2::FullMatch(converter.to_bytes(shortcut_filename),
+                            app_name + "(.*).lnk")) {
+      shortcut_path = shortcut_dir.Append(shortcut_filename);
+      if (GetShortcutProfile(shortcut_path) == profile()->GetBaseName())
+        return shortcut_path;
+    }
+  }
+#elif BUILDFLAG(IS_MAC)
+  std::string shortcut_filename = app_name + ".app";
+  shortcut_path = shortcut_dir.Append(shortcut_filename);
+  AppShimRegistry* registry = AppShimRegistry::Get();
+  // Exits early if the app id is empty because the verification won't work.
+  // TODO(crbug.com/1289865): Figure a way to find the profile that has the app
+  //                          installed without using app ID.
+  if (!app_id.empty()) {
+    std::set<base::FilePath> app_installed_profiles =
+        registry->GetInstalledProfilesForApp(app_id);
+    if (app_installed_profiles.find(profile()->GetPath()) !=
+        app_installed_profiles.end())
+      return shortcut_path;
+  }
+#elif BUILDFLAG(IS_LINUX)
+  std::string shortcut_filename =
+      "chrome-" + app_id + "-" + profile()->GetBaseName().value() + ".desktop";
+  shortcut_path = shortcut_dir.Append(shortcut_filename);
+  if (base::PathExists(shortcut_path))
+    return shortcut_path;
+#endif
+  return shortcut_path;
+}
+
 void WebAppIntegrationTestDriver::CheckAppSettingsAppState(
     Profile* profile,
     const AppState& app_state) {
@@ -1747,9 +1806,10 @@
 #elif BUILDFLAG(IS_WIN)
   DCHECK(base::Contains(g_app_name_icon_color, app_state->name));
   SkColor color = g_app_name_icon_color.find(app_state->name)->second;
-  ASSERT_TRUE(IsShortcutAndIconCorrectOnWin(
-      profile(), app_state->name, shortcut_override_->startup.GetPath(),
-      color));
+  base::FilePath startup_shortcut_path = GetShortcutPath(
+      shortcut_override_->startup.GetPath(), app_state->name, app_state->id);
+  ASSERT_TRUE(base::PathExists(startup_shortcut_path));
+  ASSERT_TRUE(GetIconTopLeftColor(startup_shortcut_path) == color);
 #elif BUILDFLAG(IS_MAC)
   std::string shortcut_filename = app_state->name + ".app";
   base::FilePath app_shortcut_path =
@@ -1773,11 +1833,9 @@
   ASSERT_FALSE(base::PathExists(
       shortcut_override_->startup.GetPath().Append(shortcut_filename)));
 #elif BUILDFLAG(IS_WIN)
-  DCHECK(base::Contains(g_app_name_icon_color, app_state->name));
-  SkColor color = g_app_name_icon_color.find(app_state->name)->second;
-  ASSERT_FALSE(IsShortcutAndIconCorrectOnWin(
-      profile(), app_state->name, shortcut_override_->startup.GetPath(),
-      color));
+  base::FilePath startup_shortcut_path = GetShortcutPath(
+      shortcut_override_->startup.GetPath(), app_state->name, app_state->id);
+  ASSERT_FALSE(base::PathExists(startup_shortcut_path));
 #elif BUILDFLAG(IS_MAC)
   std::string shortcut_filename = app_state->name + ".app";
   base::FilePath app_shortcut_path =
@@ -2341,41 +2399,28 @@
 #endif
 
 #if BUILDFLAG(IS_WIN)
-  is_shortcut_and_icon_correct =
-      (IsShortcutAndIconCorrectOnWin(profile, name,
-                                     shortcut_override_->desktop.GetPath(),
-                                     expected_icon_pixel_color) &&
-       IsShortcutAndIconCorrectOnWin(
-           profile, name, shortcut_override_->application_menu.GetPath(),
-           expected_icon_pixel_color));
+  base::FilePath desktop_shortcut_path =
+      GetShortcutPath(shortcut_override_->desktop.GetPath(), name, id);
+  base::FilePath application_menu_shortcut_path =
+      GetShortcutPath(shortcut_override_->application_menu.GetPath(), name, id);
+  if (base::PathExists(desktop_shortcut_path) &&
+      base::PathExists(application_menu_shortcut_path))
+    is_shortcut_and_icon_correct =
+        (GetIconTopLeftColor(desktop_shortcut_path) ==
+             expected_icon_pixel_color &&
+         GetIconTopLeftColor(application_menu_shortcut_path) ==
+             expected_icon_pixel_color);
 #elif BUILDFLAG(IS_MAC)
-  std::string shortcut_filename = name + ".app";
-  base::FilePath app_shortcut_path =
-      shortcut_override_->chrome_apps_folder.GetPath().Append(
-          shortcut_filename);
-  AppShimRegistry* registry = AppShimRegistry::Get();
-  bool is_app_profile_found = false;
-  // Exits early if the app id is empty because the verification won't work.
-  // TODO(crbug.com/1289865): Figure a way to find the profile that has the app
-  //                          installed without using app ID.
-  if (id.empty())
-    return false;
-  std::set<base::FilePath> app_installed_profiles =
-      registry->GetInstalledProfilesForApp(id);
-  is_app_profile_found = (app_installed_profiles.find(profile->GetPath()) !=
-                          app_installed_profiles.end());
-  bool shortcut_exists =
-      (base::PathExists(app_shortcut_path) && is_app_profile_found);
-  if (shortcut_exists) {
+  base::FilePath app_shortcut_path = GetShortcutPath(
+      shortcut_override_->chrome_apps_folder.GetPath(), name, id);
+  if (base::PathExists(app_shortcut_path)) {
     SkColor icon_pixel_color = GetIconTopLeftColor(app_shortcut_path);
     is_shortcut_and_icon_correct =
         (icon_pixel_color == expected_icon_pixel_color);
   }
 #elif BUILDFLAG(IS_LINUX)
-  std::string shortcut_filename =
-      "chrome-" + id + "-" + profile->GetBaseName().value() + ".desktop";
   base::FilePath desktop_shortcut_path =
-      shortcut_override_->desktop.GetPath().Append(shortcut_filename);
+      GetShortcutPath(shortcut_override_->desktop.GetPath(), name, id);
   if (base::PathExists(desktop_shortcut_path)) {
     is_shortcut_and_icon_correct = IconManagerCheckIconTopLeftColor(
         provider()->icon_manager(), id, {kLauncherIconSize, kInstallIconSize},
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
index 31ce948..c4ca9e27 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
@@ -204,6 +204,7 @@
   void ApplyRunOnOsLoginPolicyAllowed(Site site);
   void ApplyRunOnOsLoginPolicyBlocked(Site site);
   void ApplyRunOnOsLoginPolicyRunWindowed(Site site);
+  void DeletePlatformShortcut(Site site);
   void RemoveRunOnOsLoginPolicy(Site site);
   void LaunchFromChromeApps(Site site);
   void LaunchFromLaunchIcon(Site site);
@@ -296,6 +297,9 @@
   content::WebContents* GetCurrentTab(Browser* browser);
   GURL GetInScopeURL(Site site);
   GURL GetScopeForSiteMode(Site site);
+  base::FilePath GetShortcutPath(base::FilePath shortcut_dir,
+                                 const std::string& app_name,
+                                 const AppId& app_id);
   GURL GetURLForSiteMode(Site site);
   void InstallCreateShortcut(bool open_in_window);
 
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
index d6bd1da..89c1f714 100644
--- a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
+++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
@@ -238,8 +238,12 @@
   // to the privacy policy and terms of service URLs.
   views::StyledLabel* disclosure_label =
       row->AddChildView(std::make_unique<views::StyledLabel>());
+  // TODO(crbug.com/1324689): remove the IsRTL() check and instead replace with
+  // just gfx::HorizontalAlignment::ALIGN_LEFT when
+  // StyledLabel::SetHorizontalAlignment() does mirror in RTL.
   disclosure_label->SetHorizontalAlignment(
-      gfx::HorizontalAlignment::ALIGN_LEFT);
+      base::i18n::IsRTL() ? gfx::HorizontalAlignment::ALIGN_RIGHT
+                          : gfx::HorizontalAlignment::ALIGN_LEFT);
 
   // Set custom top and bottom margins for `disclosure_label` in order to take
   // (line_height - font_height) into account.
diff --git a/chrome/browser/url_param_filter/url_param_classifications_loader_unittest.cc b/chrome/browser/url_param_filter/url_param_classifications_loader_unittest.cc
index 78eda5d..701d706 100644
--- a/chrome/browser/url_param_filter/url_param_classifications_loader_unittest.cc
+++ b/chrome/browser/url_param_filter/url_param_classifications_loader_unittest.cc
@@ -82,6 +82,13 @@
 };
 
 TEST_F(UrlParamClassificationsLoaderTest,
+       GetClassifications_MissingComponentAndFeature) {
+  // Neither Component nor feature provide classifications.
+  EXPECT_THAT(loader()->GetSourceClassifications(), IsEmpty());
+  EXPECT_THAT(loader()->GetDestinationClassifications(), IsEmpty());
+}
+
+TEST_F(UrlParamClassificationsLoaderTest,
        ReadClassifications_NonserializedProto) {
   loader()->ReadClassifications("clearly not proto");
   EXPECT_THAT(loader()->GetSourceClassifications(), IsEmpty());
@@ -156,8 +163,25 @@
 }
 
 TEST_F(UrlParamClassificationsLoaderTest,
-       GetSourceClassifications_MissingComponentAndFeature) {
-  // Neither Component nor feature provide classifications.
+       GetSourceClassifications_NoSourceClassificationsProvided) {
+  // Create proto with only Destination classifications.
+  FilterClassifications classifications = MakeClassificationsProtoFromMap(
+      {}, {{kDestinationSite, {"plzblock3", "plzblock4"}}});
+
+  // Provide classifications from the Component.
+  SetComponentFileContents(classifications.SerializeAsString());
+  loader()->ReadClassifications(test_file_contents());
+
+  // No source classifications were loaded.
+  EXPECT_THAT(loader()->GetSourceClassifications(), IsEmpty());
+
+  // Provide classifications from the feature.
+  SetFeatureParams(
+      {{"classifications",
+        CreateBase64EncodedFilterParamClassificationForTesting(
+            {}, {{kDestinationSite, {"plzblock3", "plzblock4"}}})}});
+
+  // No source classifications were loaded.
   EXPECT_THAT(loader()->GetSourceClassifications(), IsEmpty());
 }
 
@@ -296,9 +320,25 @@
 }
 
 TEST_F(UrlParamClassificationsLoaderTest,
-       GetDestinationClassifications_MissingComponentAndFeature) {
-  // Neither Component nor feature provide classifications.
-  EXPECT_THAT(loader()->GetSourceClassifications(), IsEmpty());
+       GetDestinationClassifications_NoDestinationClassificationsProvided) {
+  // Create proto with only Source classifications.
+  FilterClassifications classifications = MakeClassificationsProtoFromMap(
+      {{kSourceSite, {"plzblock1", "plzblock2"}}}, {});
+
+  // Provide classifications from the Component.
+  SetComponentFileContents(classifications.SerializeAsString());
+  loader()->ReadClassifications(test_file_contents());
+
+  // No destination classifications were loaded.
+  EXPECT_THAT(loader()->GetDestinationClassifications(), IsEmpty());
+
+  // Provide classifications from the feature.
+  SetFeatureParams({{"classifications",
+                     CreateBase64EncodedFilterParamClassificationForTesting(
+                         {{kSourceSite, {"plzblock1", "plzblock2"}}}, {})}});
+
+  // No destination classifications were loaded.
+  EXPECT_THAT(loader()->GetDestinationClassifications(), IsEmpty());
 }
 
 TEST_F(UrlParamClassificationsLoaderTest,
diff --git a/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc b/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc
index eeb9e60e..ca655fe 100644
--- a/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/callback_helpers.h"
 #include "base/check_op.h"
 #include "base/containers/contains.h"
+#include "base/containers/flat_set.h"
 #include "base/memory/raw_ptr.h"
 #include "base/notreached.h"
 #include "base/run_loop.h"
@@ -225,7 +226,7 @@
   }
 
   void RetryIncompleteUninstalls(
-      const std::vector<AppId>& apps_to_uninstall) override {
+      const base::flat_set<AppId>& apps_to_uninstall) override {
     NOTREACHED();
   }
 
diff --git a/chrome/browser/web_applications/preinstalled_app_install_features.cc b/chrome/browser/web_applications/preinstalled_app_install_features.cc
index 06fd447..6633cd4 100644
--- a/chrome/browser/web_applications/preinstalled_app_install_features.cc
+++ b/chrome/browser/web_applications/preinstalled_app_install_features.cc
@@ -75,7 +75,7 @@
 
 // Enables installing the Messages app on unmanaged devices.
 const base::Feature kMessagesPreinstall{"MessagesPreinstall",
-                                        base::FEATURE_DISABLED_BY_DEFAULT};
+                                        base::FEATURE_ENABLED_BY_DEFAULT};
 
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager.cc b/chrome/browser/web_applications/preinstalled_web_app_manager.cc
index 08bd1e88..2eb6072 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_manager.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_manager.cc
@@ -70,6 +70,10 @@
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "chromeos/lacros/lacros_service.h"
+#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
+
 namespace web_app {
 
 namespace {
@@ -120,6 +124,30 @@
   std::vector<std::string> errors;
 };
 
+#if BUILDFLAG(IS_CHROMEOS)
+bool IsArcAvailable() {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  return arc::IsArcAvailable();
+#else
+  const crosapi::mojom::BrowserInitParams* init_params =
+      chromeos::LacrosService::Get()->init_params();
+  return init_params && init_params->device_properties &&
+         init_params->device_properties->is_arc_available;
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+}
+
+bool IsTabletFormFactor() {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  return ash::switches::IsTabletFormFactor();
+#else
+  const crosapi::mojom::BrowserInitParams* init_params =
+      chromeos::LacrosService::Get()->init_params();
+  return init_params && init_params->device_properties &&
+         init_params->device_properties->is_tablet_form_factor;
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+}
+#endif  // BUILDFLAG(IS_CHROMEOS)
+
 LoadedConfigs LoadConfigsBlocking(
     const std::vector<base::FilePath>& config_dirs) {
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
@@ -235,22 +263,21 @@
     }
   }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
   // Remove if ARC is supported and app should be disabled.
-  if (options.disable_if_arc_supported && arc::IsArcAvailable()) {
+  if (options.disable_if_arc_supported && IsArcAvailable()) {
     base::UmaHistogramEnumeration(kHistogramMigrationDisabledReason,
                                   DisabledReason::kArcAvailable);
     return options.install_url.spec() + " disabled because ARC is available.";
   }
 
   // Remove if device is tablet and app should be disabled.
-  if (options.disable_if_tablet_form_factor &&
-      ash::switches::IsTabletFormFactor()) {
+  if (options.disable_if_tablet_form_factor && IsTabletFormFactor()) {
     base::UmaHistogramEnumeration(kHistogramMigrationDisabledReason,
                                   DisabledReason::kTabletFormFactor);
     return options.install_url.spec() + " disabled because device is tablet.";
   }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Remove if only for new users, user isn't new and app was not
   // installed previously.
diff --git a/chrome/browser/web_applications/test/fake_install_finalizer.cc b/chrome/browser/web_applications/test/fake_install_finalizer.cc
index 09e9729..1e753a91 100644
--- a/chrome/browser/web_applications/test/fake_install_finalizer.cc
+++ b/chrome/browser/web_applications/test/fake_install_finalizer.cc
@@ -4,6 +4,7 @@
 
 #include <utility>
 
+#include "base/containers/flat_set.h"
 #include "chrome/browser/web_applications/test/fake_install_finalizer.h"
 
 #include "base/callback.h"
@@ -95,7 +96,7 @@
 }
 
 void FakeInstallFinalizer::RetryIncompleteUninstalls(
-    const std::vector<AppId>& apps_to_uninstall) {
+    const base::flat_set<AppId>& apps_to_uninstall) {
   NOTREACHED();
 }
 
diff --git a/chrome/browser/web_applications/test/fake_install_finalizer.h b/chrome/browser/web_applications/test/fake_install_finalizer.h
index 88a98cc..2e87b4a 100644
--- a/chrome/browser/web_applications/test/fake_install_finalizer.h
+++ b/chrome/browser/web_applications/test/fake_install_finalizer.h
@@ -9,6 +9,7 @@
 #include <memory>
 #include <set>
 
+#include "base/containers/flat_set.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -48,7 +49,7 @@
                        webapps::WebappUninstallSource uninstall_source,
                        UninstallWebAppCallback callback) override;
   void RetryIncompleteUninstalls(
-      const std::vector<AppId>& apps_to_uninstall) override;
+      const base::flat_set<AppId>& apps_to_uninstall) override;
   bool WasPreinstalledWebAppUninstalled(const AppId& app_id) const override;
   bool CanReparentTab(const AppId& app_id,
                       bool shortcut_created) const override;
diff --git a/chrome/browser/web_applications/test/fake_web_app_registry_controller.cc b/chrome/browser/web_applications/test/fake_web_app_registry_controller.cc
index d2c0d504..b7a08c7 100644
--- a/chrome/browser/web_applications/test/fake_web_app_registry_controller.cc
+++ b/chrome/browser/web_applications/test/fake_web_app_registry_controller.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/web_applications/test/fake_web_app_registry_controller.h"
 
+#include "base/containers/flat_set.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
@@ -132,7 +133,7 @@
 }
 
 void FakeWebAppRegistryController::RetryIncompleteUninstalls(
-    const std::vector<AppId>& apps_to_uninstall) {
+    const base::flat_set<AppId>& apps_to_uninstall) {
   if (retry_incomplete_uninstalls_delegate_)
     retry_incomplete_uninstalls_delegate_.Run(apps_to_uninstall);
 }
diff --git a/chrome/browser/web_applications/test/fake_web_app_registry_controller.h b/chrome/browser/web_applications/test/fake_web_app_registry_controller.h
index 276c5ad..295ee39 100644
--- a/chrome/browser/web_applications/test/fake_web_app_registry_controller.h
+++ b/chrome/browser/web_applications/test/fake_web_app_registry_controller.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/callback.h"
+#include "base/containers/flat_set.h"
 #include "chrome/browser/web_applications/test/fake_externally_managed_app_manager.h"
 #include "chrome/browser/web_applications/test/fake_os_integration_manager.h"
 #include "chrome/browser/web_applications/web_app_id.h"
@@ -58,7 +59,7 @@
   void SetUninstallFromSyncDelegate(UninstallFromSyncDelegate delegate);
 
   using RetryIncompleteUninstallsDelegate = base::RepeatingCallback<void(
-      const std::vector<AppId>& apps_to_uninstall)>;
+      const base::flat_set<AppId>& apps_to_uninstall)>;
   void SetRetryIncompleteUninstallsDelegate(
       RetryIncompleteUninstallsDelegate delegate);
 
@@ -68,7 +69,7 @@
   void UninstallFromSync(const std::vector<AppId>& web_apps,
                          RepeatingUninstallCallback callback) override;
   void RetryIncompleteUninstalls(
-      const std::vector<AppId>& apps_to_uninstall) override;
+      const base::flat_set<AppId>& apps_to_uninstall) override;
 
   void DestroySubsystems();
 
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 25ab84e..0d2d51a 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -12,6 +12,7 @@
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/containers/contains.h"
+#include "base/containers/flat_set.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
@@ -311,16 +312,18 @@
 }
 
 void WebAppInstallFinalizer::RetryIncompleteUninstalls(
-    const std::vector<AppId>& apps_to_uninstall) {
+    const base::flat_set<AppId>& apps_to_uninstall) {
   for (const AppId& app_id : apps_to_uninstall) {
     if (base::Contains(pending_uninstalls_, app_id))
       continue;
     auto uninstall_task = std::make_unique<WebAppUninstallJob>(
         os_integration_manager_, sync_bridge_, icon_manager_, registrar_,
         install_manager_, this, translation_manager_, profile_->GetPrefs());
+    const WebApp* web_app = registrar_->GetAppById(app_id);
+    if (!web_app)
+      continue;
     uninstall_task->Start(
-        app_id,
-        url::Origin::Create(registrar_->GetAppById(app_id)->start_url()),
+        app_id, url::Origin::Create(web_app->start_url()),
         webapps::WebappUninstallSource::kStartupCleanup,
         base::BindOnce(&WebAppInstallFinalizer::OnUninstallComplete,
                        weak_ptr_factory_.GetWeakPtr(), app_id,
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h
index 904f0cf..150e27b6 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.h
+++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/callback_forward.h"
+#include "base/containers/flat_set.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
@@ -124,7 +125,7 @@
                                UninstallWebAppCallback callback);
 
   virtual void RetryIncompleteUninstalls(
-      const std::vector<AppId>& apps_to_uninstall);
+      const base::flat_set<AppId>& apps_to_uninstall);
 
   // Sync-initiated uninstall. Copied from WebAppInstallSyncInstallDelegate.
   // Called before the web apps are removed from the registry by sync. This:
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc
index f9b6034..7380445 100644
--- a/chrome/browser/web_applications/web_app_install_manager.cc
+++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -294,7 +294,7 @@
 }
 
 void WebAppInstallManager::RetryIncompleteUninstalls(
-    const std::vector<AppId>& apps_to_uninstall) {
+    const base::flat_set<AppId>& apps_to_uninstall) {
   if (!started_)
     return;
 
diff --git a/chrome/browser/web_applications/web_app_install_manager.h b/chrome/browser/web_applications/web_app_install_manager.h
index 0ddab13..7b00a08 100644
--- a/chrome/browser/web_applications/web_app_install_manager.h
+++ b/chrome/browser/web_applications/web_app_install_manager.h
@@ -83,7 +83,7 @@
   void UninstallFromSync(const std::vector<AppId>& web_apps,
                          RepeatingUninstallCallback callback) override;
   void RetryIncompleteUninstalls(
-      const std::vector<AppId>& apps_to_uninstall) override;
+      const base::flat_set<AppId>& apps_to_uninstall) override;
 
   virtual void AddObserver(WebAppInstallManagerObserver* observer);
   virtual void RemoveObserver(WebAppInstallManagerObserver* observer);
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.cc b/chrome/browser/web_applications/web_app_sync_bridge.cc
index fd05b49..ddb8d265 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge.cc
+++ b/chrome/browser/web_applications/web_app_sync_bridge.cc
@@ -806,7 +806,8 @@
                               apps_uninstalling.size());
 
   if (!apps_uninstalling.empty())
-    install_delegate_->RetryIncompleteUninstalls(apps_uninstalling);
+    install_delegate_->RetryIncompleteUninstalls(
+        base::flat_set<AppId>(std::move(apps_uninstalling)));
 }
 
 void WebAppSyncBridge::MaybeInstallAppsFromSyncAndPendingInstallation() {
diff --git a/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc b/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc
index 67c6194..1aaf8fc4 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc
+++ b/chrome/browser/web_applications/web_app_sync_bridge_unittest.cc
@@ -1202,7 +1202,7 @@
 
   base::RunLoop run_loop;
   controller().SetRetryIncompleteUninstallsDelegate(base::BindLambdaForTesting(
-      [&](const std::vector<AppId>& apps_to_uninstall) {
+      [&](const base::flat_set<AppId>& apps_to_uninstall) {
         EXPECT_EQ(apps_to_uninstall.size(), 5ul);
         EXPECT_THAT(apps_to_uninstall,
                     ::testing::UnorderedElementsAreArray(apps_to_uninstall));
diff --git a/chrome/browser/web_applications/web_app_sync_install_delegate.h b/chrome/browser/web_applications/web_app_sync_install_delegate.h
index 0f25db2..e96dfd7 100644
--- a/chrome/browser/web_applications/web_app_sync_install_delegate.h
+++ b/chrome/browser/web_applications/web_app_sync_install_delegate.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/callback_forward.h"
+#include "base/containers/flat_set.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "components/webapps/browser/install_result_code.h"
 
@@ -48,7 +49,7 @@
   // `is_uninstalling()` set to true. They are expected to be eventually deleted
   // by this call.
   virtual void RetryIncompleteUninstalls(
-      const std::vector<AppId>& apps_to_uninstall) = 0;
+      const base::flat_set<AppId>& apps_to_uninstall) = 0;
 };
 
 }  // namespace web_app
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 4e66c63..900ed41 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1652269806-c775896d86e82f4519f8f40d3b56cb63eb230464.profdata
+chrome-win32-main-1652281130-548231baae8bd6719cebf30c54e84ee6477dbcb0.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 59204c5..8f4f880 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1652269806-4d3146697929c887bfda350facd82334703fe632.profdata
+chrome-win64-main-1652281130-ca75a3ac44f3a696888ee7d473f8f28b8f7f45d7.profdata
diff --git a/chrome/services/system_signals/DEPS b/chrome/services/system_signals/DEPS
new file mode 100644
index 0000000..3d8961f
--- /dev/null
+++ b/chrome/services/system_signals/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/device_signals/core/common",
+]
diff --git a/chrome/services/system_signals/OWNERS b/chrome/services/system_signals/OWNERS
index eb5ae5e..9aeb8c8 100644
--- a/chrome/services/system_signals/OWNERS
+++ b/chrome/services/system_signals/OWNERS
@@ -1,2 +1 @@
-seblalancette@chromium.org
-rogerta@chromium.org
+file://components/device_signals/OWNERS
diff --git a/chrome/services/system_signals/linux/BUILD.gn b/chrome/services/system_signals/linux/BUILD.gn
index 39b6d437..bdab721 100644
--- a/chrome/services/system_signals/linux/BUILD.gn
+++ b/chrome/services/system_signals/linux/BUILD.gn
@@ -9,7 +9,7 @@
 
   sources = [ "linux_system_signals_service.cc" ]
 
-  public_deps = [ "//chrome/services/system_signals/public/mojom" ]
+  public_deps = [ "//components/device_signals/core/common/mojom" ]
 
   deps = [ "//base" ]
 }
diff --git a/chrome/services/system_signals/linux/linux_system_signals_service.cc b/chrome/services/system_signals/linux/linux_system_signals_service.cc
index 08df8322..fe1338bb 100644
--- a/chrome/services/system_signals/linux/linux_system_signals_service.cc
+++ b/chrome/services/system_signals/linux/linux_system_signals_service.cc
@@ -10,7 +10,7 @@
 LinuxSystemSignalsService::~LinuxSystemSignalsService() = default;
 
 void LinuxSystemSignalsService::GetBinarySignals(
-    std::vector<mojom::BinarySignalsRequestPtr> requests,
+    std::vector<device_signals::mojom::BinarySignalsRequestPtr> requests,
     GetBinarySignalsCallback callback) {
   // TODO(b/231326345): Implement this.
   std::move(callback).Run({});
diff --git a/chrome/services/system_signals/linux/linux_system_signals_service.h b/chrome/services/system_signals/linux/linux_system_signals_service.h
index ba36d30c..c233414 100644
--- a/chrome/services/system_signals/linux/linux_system_signals_service.h
+++ b/chrome/services/system_signals/linux/linux_system_signals_service.h
@@ -7,11 +7,12 @@
 
 #include <vector>
 
-#include "chrome/services/system_signals/public/mojom/system_signals.mojom.h"
+#include "components/device_signals/core/common/mojom/system_signals.mojom.h"
 
 namespace system_signals {
 
-class LinuxSystemSignalsService : public mojom::SystemSignalsService {
+class LinuxSystemSignalsService
+    : public device_signals::mojom::SystemSignalsService {
  public:
   LinuxSystemSignalsService();
   ~LinuxSystemSignalsService() override;
@@ -20,9 +21,10 @@
   LinuxSystemSignalsService& operator=(const LinuxSystemSignalsService&) =
       delete;
 
-  // mojom::SystemSignalsService:
-  void GetBinarySignals(std::vector<mojom::BinarySignalsRequestPtr> requests,
-                        GetBinarySignalsCallback callback) override;
+  // device_signals::mojom::SystemSignalsService:
+  void GetBinarySignals(
+      std::vector<device_signals::mojom::BinarySignalsRequestPtr> requests,
+      GetBinarySignalsCallback callback) override;
 };
 
 }  // namespace system_signals
diff --git a/chrome/services/system_signals/mac/BUILD.gn b/chrome/services/system_signals/mac/BUILD.gn
index 618ebdf..7b209f8 100644
--- a/chrome/services/system_signals/mac/BUILD.gn
+++ b/chrome/services/system_signals/mac/BUILD.gn
@@ -9,7 +9,7 @@
 
   sources = [ "mac_system_signals_service.cc" ]
 
-  public_deps = [ "//chrome/services/system_signals/public/mojom" ]
+  public_deps = [ "//components/device_signals/core/common/mojom" ]
 
   deps = [ "//base" ]
 }
diff --git a/chrome/services/system_signals/mac/mac_system_signals_service.h b/chrome/services/system_signals/mac/mac_system_signals_service.h
index b65c9b3..7cefec4 100644
--- a/chrome/services/system_signals/mac/mac_system_signals_service.h
+++ b/chrome/services/system_signals/mac/mac_system_signals_service.h
@@ -7,11 +7,12 @@
 
 #include <vector>
 
-#include "chrome/services/system_signals/public/mojom/system_signals.mojom.h"
+#include "components/device_signals/core/common/mojom/system_signals.mojom.h"
 
 namespace system_signals {
 
-class MacSystemSignalsService : public mojom::SystemSignalsService {
+class MacSystemSignalsService
+    : public device_signals::mojom::SystemSignalsService {
  public:
   MacSystemSignalsService();
   ~MacSystemSignalsService() override;
@@ -19,9 +20,10 @@
   MacSystemSignalsService(const MacSystemSignalsService&) = delete;
   MacSystemSignalsService& operator=(const MacSystemSignalsService&) = delete;
 
-  // mojom::SystemSignalsService:
-  void GetBinarySignals(std::vector<mojom::BinarySignalsRequestPtr> requests,
-                        GetBinarySignalsCallback callback) override;
+  // device_signals::mojom::SystemSignalsService:
+  void GetBinarySignals(
+      std::vector<device_signals::mojom::BinarySignalsRequestPtr> requests,
+      GetBinarySignalsCallback callback) override;
 };
 
 }  // namespace system_signals
diff --git a/chrome/services/system_signals/mac/mac_system_signals_service.mm b/chrome/services/system_signals/mac/mac_system_signals_service.mm
index cd79730..c9eddba1 100644
--- a/chrome/services/system_signals/mac/mac_system_signals_service.mm
+++ b/chrome/services/system_signals/mac/mac_system_signals_service.mm
@@ -10,7 +10,7 @@
 MacSystemSignalsService::~MacSystemSignalsService() = default;
 
 void LinuxSystemSignalsService::GetBinarySignals(
-    std::vector<mojom::BinarySignalsRequestPtr> requests,
+    std::vector<device_signals::mojom::BinarySignalsRequestPtr> requests,
     GetBinarySignalsCallback callback) {
   // TODO(b/231326198): Implement this.
   std::move(callback).Run({});
diff --git a/chrome/services/system_signals/public/cpp/BUILD.gn b/chrome/services/system_signals/public/cpp/BUILD.gn
index 85e8e6a..99efa58 100644
--- a/chrome/services/system_signals/public/cpp/BUILD.gn
+++ b/chrome/services/system_signals/public/cpp/BUILD.gn
@@ -11,7 +11,7 @@
 
   public_deps = [
     "//build",
-    "//chrome/services/system_signals/public/mojom",
+    "//components/device_signals/core/common/mojom",
     "//mojo/public/mojom/base",
   ]
 
diff --git a/chrome/services/system_signals/public/cpp/system_signals_service_host.cc b/chrome/services/system_signals/public/cpp/system_signals_service_host.cc
index 24e4c26..5f99d1f5 100644
--- a/chrome/services/system_signals/public/cpp/system_signals_service_host.cc
+++ b/chrome/services/system_signals/public/cpp/system_signals_service_host.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/services/system_signals/public/cpp/system_signals_service_host.h"
 
-#include "chrome/services/system_signals/public/mojom/system_signals.mojom.h"
+#include "components/device_signals/core/common/mojom/system_signals.mojom.h"
 
 #if BUILDFLAG(IS_WIN)
 #include "base/time/time.h"
@@ -23,16 +23,17 @@
 
 #if BUILDFLAG(IS_WIN)
 
-mojom::SystemSignalsService* SystemSignalsServiceHost::GetService() {
+device_signals::mojom::SystemSignalsService*
+SystemSignalsServiceHost::GetService() {
   // To prevent any impact on Chrome's stability and memory footprint, run
   // this service in its own process on Windows (since it interacts with, e.g.,
   // WMI).
   if (!remote_service_) {
-    remote_service_ =
-        content::ServiceProcessHost::Launch<mojom::SystemSignalsService>(
-            content::ServiceProcessHost::Options()
-                .WithDisplayName(IDS_UTILITY_PROCESS_SYSTEM_SIGNALS_NAME)
-                .Pass());
+    remote_service_ = content::ServiceProcessHost::Launch<
+        device_signals::mojom::SystemSignalsService>(
+        content::ServiceProcessHost::Options()
+            .WithDisplayName(IDS_UTILITY_PROCESS_SYSTEM_SIGNALS_NAME)
+            .Pass());
     remote_service_.reset_on_idle_timeout(base::Seconds(10));
   }
   return &remote_service_;
@@ -40,7 +41,8 @@
 
 #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
 
-mojom::SystemSignalsService* SystemSignalsServiceHost::GetService() {
+device_signals::mojom::SystemSignalsService*
+SystemSignalsServiceHost::GetService() {
   if (!local_service_) {
 #if BUILDFLAG(IS_MAC)
     local_service_ = std::make_unique<MacSystemSignalsService>();
diff --git a/chrome/services/system_signals/public/cpp/system_signals_service_host.h b/chrome/services/system_signals/public/cpp/system_signals_service_host.h
index 82d82349..08db1ba9 100644
--- a/chrome/services/system_signals/public/cpp/system_signals_service_host.h
+++ b/chrome/services/system_signals/public/cpp/system_signals_service_host.h
@@ -6,7 +6,7 @@
 #define CHROME_SERVICES_SYSTEM_SIGNALS_PUBLIC_CPP_SYSTEM_SIGNALS_SERVICE_HOST_H_
 
 #include "build/build_config.h"
-#include "chrome/services/system_signals/public/mojom/system_signals.mojom-forward.h"
+#include "components/device_signals/core/common/mojom/system_signals.mojom-forward.h"
 
 #if BUILDFLAG(IS_WIN)
 #include "mojo/public/cpp/bindings/remote.h"
@@ -28,13 +28,13 @@
   SystemSignalsServiceHost& operator=(const SystemSignalsServiceHost&) = delete;
 
   // Returns a pointer to the currently available SystemSignalsService instance.
-  mojom::SystemSignalsService* GetService();
+  device_signals::mojom::SystemSignalsService* GetService();
 
  private:
 #if BUILDFLAG(IS_WIN)
-  mojom::Remote<mojom::SystemSignalsService> remote_service_;
+  mojom::Remote<device_signals::mojom::SystemSignalsService> remote_service_;
 #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
-  std::unique_ptr<mojom::SystemSignalsService> local_service_;
+  std::unique_ptr<device_signals::mojom::SystemSignalsService> local_service_;
 #endif
 };
 
diff --git a/chrome/services/system_signals/win/BUILD.gn b/chrome/services/system_signals/win/BUILD.gn
index 2bba505c..6ef9a4d 100644
--- a/chrome/services/system_signals/win/BUILD.gn
+++ b/chrome/services/system_signals/win/BUILD.gn
@@ -10,7 +10,7 @@
   sources = [ "win_system_signals_service.cc" ]
 
   public_deps = [
-    "//chrome/services/system_signals/public/mojom",
+    "//components/device_signals/core/common/mojom",
     "//mojo/public/mojom/base",
   ]
 
diff --git a/chrome/services/system_signals/win/win_system_signals_service.cc b/chrome/services/system_signals/win/win_system_signals_service.cc
index c0c95958..ab3848e 100644
--- a/chrome/services/system_signals/win/win_system_signals_service.cc
+++ b/chrome/services/system_signals/win/win_system_signals_service.cc
@@ -7,13 +7,13 @@
 namespace system_signals {
 
 WinSystemSignalsService::WinSystemSignalsService(
-    mojo::PendingReceiver<mojom::SystemSignalsService> receiver)
+    mojo::PendingReceiver<device_signals::mojom::SystemSignalsService> receiver)
     : receiver_(this, std::move(receiver)) {}
 
 WinSystemSignalsService::~WinSystemSignalsService() = default;
 
 void WinSystemSignalsService::GetBinarySignals(
-    std::vector<mojom::BinarySignalsRequestPtr> requests,
+    std::vector<device_signals::mojom::BinarySignalsRequestPtr> requests,
     GetBinarySignalsCallback callback) {
   // TODO(b/231298500): Implement this.
   std::move(callback).Run({});
diff --git a/chrome/services/system_signals/win/win_system_signals_service.h b/chrome/services/system_signals/win/win_system_signals_service.h
index 7f6d6eb..f03e8d51 100644
--- a/chrome/services/system_signals/win/win_system_signals_service.h
+++ b/chrome/services/system_signals/win/win_system_signals_service.h
@@ -7,29 +7,32 @@
 
 #include <vector>
 
-#include "chrome/services/system_signals/public/mojom/system_signals.mojom.h"
+#include "components/device_signals/core/common/mojom/system_signals.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 
 namespace system_signals {
 
-class WinSystemSignalsService : public mojom::SystemSignalsService {
+class WinSystemSignalsService
+    : public device_signals::mojom::SystemSignalsService {
  public:
   explicit WinSystemSignalsService(
-      mojo::PendingReceiver<mojom::SystemSignalsService> receiver);
+      mojo::PendingReceiver<device_signals::mojom::SystemSignalsService>
+          receiver);
   ~WinSystemSignalsService() override;
 
   WinSystemSignalsService(const WinSystemSignalsService&) = delete;
   WinSystemSignalsService& operator=(const WinSystemSignalsService&) = delete;
 
   // mojom::SystemSignalsService:
-  void GetBinarySignals(std::vector<mojom::BinarySignalsRequestPtr> requests,
-                        GetBinarySignalsCallback callback) override;
+  void GetBinarySignals(
+      std::vector<device_signals::mojom::BinarySignalsRequestPtr> requests,
+      GetBinarySignalsCallback callback) override;
   void GetAntiVirusSignals(GetAntiVirusSignalsCallback callback) override;
   void GetHotfixSignals(GetHotfixSignalsCallback callback) override;
 
  private:
-  mojo::Receiver<mojom::SystemSignalsService> receiver_;
+  mojo::Receiver<device_signals::mojom::SystemSignalsService> receiver_;
 };
 
 }  // namespace system_signals
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 8dacd2ac..1b3b6de 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1996,6 +1996,7 @@
       "../browser/site_isolation/chrome_site_per_process_browsertest.cc",
       "../browser/site_isolation/chrome_site_per_process_test.cc",
       "../browser/site_isolation/chrome_site_per_process_test.h",
+      "../browser/site_isolation/isolated_sandboxed_iframe_browsertest.cc",
       "../browser/site_isolation/origin_agent_cluster_browsertest.cc",
       "../browser/site_isolation/site_details_browsertest.cc",
       "../browser/spellchecker/spellcheck_service_browsertest.cc",
@@ -2654,6 +2655,9 @@
       sources += [
         "../browser/external_protocol/external_protocol_policy_browsertest.cc",
         "../browser/lifetime/application_lifetime_browsertest.cc",
+
+        # crbug.com/1323505 Enable DownloadBubble tests on ChromeOS.
+        "../browser/ui/views/download/bubble/download_bubble_dialog_browsertest.cc",
       ]
     }
 
diff --git a/chrome/test/data/pdf/accessibility/hello-world-expected-mac.txt b/chrome/test/data/pdf/accessibility/hello-world-expected-mac.txt
index 5bc0cec..78a984b 100644
--- a/chrome/test/data/pdf/accessibility/hello-world-expected-mac.txt
+++ b/chrome/test/data/pdf/accessibility/hello-world-expected-mac.txt
@@ -1,4 +1,4 @@
 AXGroup AXDescription='PDF document containing 1 page'
-AXGroup AXSubrole=AXLandmarkRegion AXDescription='Page 1'
+++AXGroup AXSubrole=AXLandmarkRegion AXDescription='Page 1'
 ++++AXGroup
 ++++++AXStaticText AXValue='Hello, world!'
diff --git a/chrome/test/data/pdf/accessibility/text_fields-expected-mac.txt b/chrome/test/data/pdf/accessibility/text_fields-expected-mac.txt
index 625f625..49edd49 100644
--- a/chrome/test/data/pdf/accessibility/text_fields-expected-mac.txt
+++ b/chrome/test/data/pdf/accessibility/text_fields-expected-mac.txt
@@ -13,4 +13,4 @@
 ++++++AXTextField AXDescription='Text Box' AXValue='Text'
 ++++++AXTextField AXDescription='ReadOnly' AXValue='Elephant'
 ++++++AXTextField AXDescription='Required' AXValue='Required Field'
-++++++AXTextField AXDescription='Password'
+++++++AXTextField AXSubrole=AXSecureTextField AXDescription='Password'
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn
index b07269f..be69c3b5 100644
--- a/chrome/updater/BUILD.gn
+++ b/chrome/updater/BUILD.gn
@@ -82,8 +82,6 @@
       "crash_reporter.cc",
       "crash_reporter.h",
       "crx_downloader_factory.h",
-      "device_management/cloud_policy_util.cc",
-      "device_management/cloud_policy_util.h",
       "device_management/dm_cached_policy_info.cc",
       "device_management/dm_cached_policy_info.h",
       "device_management/dm_client.cc",
@@ -157,6 +155,7 @@
       "//components/crash/core/common:crash_key",
       "//components/crash/core/common:crash_key_lib",
       "//components/crx_file",
+      "//components/policy/core/common",
       "//components/policy/proto",
       "//components/prefs",
       "//components/update_client",
diff --git a/chrome/updater/device_management/cloud_policy_util.cc b/chrome/updater/device_management/cloud_policy_util.cc
deleted file mode 100644
index fb7ba7d..0000000
--- a/chrome/updater/device_management/cloud_policy_util.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Code in this file are branched from
-// components/policy/core/common/cloud/cloud_policy_constants.cc and
-// components/policy/core/common/cloud/cloud_policy_util.cc. In the long
-// term, we should reuse the code (crbug/1219760).
-
-#include "chrome/updater/device_management/cloud_policy_util.h"
-
-#include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
-
-#if BUILDFLAG(IS_WIN)
-#include <Windows.h>  // For GetComputerNameW()
-// SECURITY_WIN32 must be defined in order to get
-// EXTENDED_NAME_FORMAT enumeration.
-#define SECURITY_WIN32 1
-#include <security.h>
-#undef SECURITY_WIN32
-#include <wincred.h>
-#endif
-
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
-#include <pwd.h>
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
-#if BUILDFLAG(IS_MAC)
-#import <SystemConfiguration/SCDynamicStoreCopySpecific.h>
-#include <stddef.h>
-#include <sys/sysctl.h>
-#endif
-
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#if BUILDFLAG(IS_LINUX)
-#include <limits.h>  // For HOST_NAME_MAX
-#endif
-
-#include <utility>
-
-#include "base/check.h"
-#include "base/cxx17_backports.h"
-#include "base/notreached.h"
-#include "base/system/sys_info.h"
-
-#if BUILDFLAG(IS_WIN)
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/windows_version.h"
-#include "base/win/wmi.h"
-#endif
-
-#if BUILDFLAG(IS_MAC)
-#include "base/mac/scoped_cftyperef.h"
-#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/system/sys_info.h"
-#endif
-
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#if BUILDFLAG(IS_LINUX)
-#include "base/system/sys_info.h"
-#endif
-
-#include "components/policy/proto/device_management_backend.pb.h"
-#include "components/version_info/version_info.h"
-
-namespace updater {
-
-namespace policy {
-
-constexpr uint8_t kPolicyVerificationKey[] = {
-    0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
-    0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00,
-    0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xA7, 0xB3, 0xF9,
-    0x0D, 0xC7, 0xC7, 0x8D, 0x84, 0x3D, 0x4B, 0x80, 0xDD, 0x9A, 0x2F, 0xF8,
-    0x69, 0xD4, 0xD1, 0x14, 0x5A, 0xCA, 0x04, 0x4B, 0x1C, 0xBC, 0x28, 0xEB,
-    0x5E, 0x10, 0x01, 0x36, 0xFD, 0x81, 0xEB, 0xE4, 0x3C, 0x16, 0x40, 0xA5,
-    0x8A, 0xE6, 0x08, 0xEE, 0xEF, 0x39, 0x1F, 0x6B, 0x10, 0x29, 0x50, 0x84,
-    0xCE, 0xEE, 0x33, 0x5C, 0x48, 0x4A, 0x33, 0xB0, 0xC8, 0x8A, 0x66, 0x0D,
-    0x10, 0x11, 0x9D, 0x6B, 0x55, 0x4C, 0x9A, 0x62, 0x40, 0x9A, 0xE2, 0xCA,
-    0x21, 0x01, 0x1F, 0x10, 0x1E, 0x7B, 0xC6, 0x89, 0x94, 0xDA, 0x39, 0x69,
-    0xBE, 0x27, 0x28, 0x50, 0x5E, 0xA2, 0x55, 0xB9, 0x12, 0x3C, 0x79, 0x6E,
-    0xDF, 0x24, 0xBF, 0x34, 0x88, 0xF2, 0x5E, 0xD0, 0xC4, 0x06, 0xEE, 0x95,
-    0x6D, 0xC2, 0x14, 0xBF, 0x51, 0x7E, 0x3F, 0x55, 0x10, 0x85, 0xCE, 0x33,
-    0x8F, 0x02, 0x87, 0xFC, 0xD2, 0xDD, 0x42, 0xAF, 0x59, 0xBB, 0x69, 0x3D,
-    0xBC, 0x77, 0x4B, 0x3F, 0xC7, 0x22, 0x0D, 0x5F, 0x72, 0xC7, 0x36, 0xB6,
-    0x98, 0x3D, 0x03, 0xCD, 0x2F, 0x68, 0x61, 0xEE, 0xF4, 0x5A, 0xF5, 0x07,
-    0xAE, 0xAE, 0x79, 0xD1, 0x1A, 0xB2, 0x38, 0xE0, 0xAB, 0x60, 0x5C, 0x0C,
-    0x14, 0xFE, 0x44, 0x67, 0x2C, 0x8A, 0x08, 0x51, 0x9C, 0xCD, 0x3D, 0xDB,
-    0x13, 0x04, 0x57, 0xC5, 0x85, 0xB6, 0x2A, 0x0F, 0x02, 0x46, 0x0D, 0x2D,
-    0xCA, 0xE3, 0x3F, 0x84, 0x9E, 0x8B, 0x8A, 0x5F, 0xFC, 0x4D, 0xAA, 0xBE,
-    0xBD, 0xE6, 0x64, 0x9F, 0x26, 0x9A, 0x2B, 0x97, 0x69, 0xA9, 0xBA, 0x0B,
-    0xBD, 0x48, 0xE4, 0x81, 0x6B, 0xD4, 0x4B, 0x78, 0xE6, 0xAF, 0x95, 0x66,
-    0xC1, 0x23, 0xDA, 0x23, 0x45, 0x36, 0x6E, 0x25, 0xF3, 0xC7, 0xC0, 0x61,
-    0xFC, 0xEC, 0x66, 0x9D, 0x31, 0xD4, 0xD6, 0xB6, 0x36, 0xE3, 0x7F, 0x81,
-    0x87, 0x02, 0x03, 0x01, 0x00, 0x01};
-
-const char kPolicyVerificationKeyHash[] = "1:356l7w";
-
-std::string GetPolicyVerificationKey() {
-  return std::string(reinterpret_cast<const char*>(kPolicyVerificationKey),
-                     sizeof(kPolicyVerificationKey));
-}
-
-std::string GetMachineName() {
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
-  char hostname[HOST_NAME_MAX];
-  if (gethostname(hostname, HOST_NAME_MAX) == 0)  // Success.
-    return hostname;
-  return std::string();
-#elif BUILDFLAG(IS_MAC)
-  // Do not use NSHost currentHost, as it's very slow. http://crbug.com/138570
-  SCDynamicStoreContext context = {0, NULL, NULL, NULL};
-  base::ScopedCFTypeRef<SCDynamicStoreRef> store(SCDynamicStoreCreate(
-      kCFAllocatorDefault, CFSTR("chrome_sync"), NULL, &context));
-  base::ScopedCFTypeRef<CFStringRef> machine_name(
-      SCDynamicStoreCopyLocalHostName(store.get()));
-  if (machine_name.get())
-    return base::SysCFStringRefToUTF8(machine_name.get());
-
-  // Fall back to get computer name.
-  base::ScopedCFTypeRef<CFStringRef> computer_name(
-      SCDynamicStoreCopyComputerName(store.get(), NULL));
-  if (computer_name.get())
-    return base::SysCFStringRefToUTF8(computer_name.get());
-
-  // If all else fails, return to using a slightly nicer version of the
-  // hardware model.
-  char modelBuffer[256];
-  size_t length = sizeof(modelBuffer);
-  if (!sysctlbyname("hw.model", modelBuffer, &length, NULL, 0)) {
-    for (size_t i = 0; i < length; i++) {
-      if (base::IsAsciiDigit(modelBuffer[i]))
-        return std::string(modelBuffer, 0, i);
-    }
-    return std::string(modelBuffer, 0, length);
-  }
-  return std::string();
-#elif BUILDFLAG(IS_WIN)
-  wchar_t computer_name[MAX_COMPUTERNAME_LENGTH + 1] = {0};
-  DWORD size = std::size(computer_name);
-  if (::GetComputerNameW(computer_name, &size)) {
-    std::string result;
-    bool conversion_successful = base::WideToUTF8(computer_name, size, &result);
-    DCHECK(conversion_successful);
-    return result;
-  }
-  return std::string();
-#else
-  NOTREACHED();
-  return std::string();
-#endif
-}
-
-std::string GetOSVersion() {
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
-  return base::SysInfo::OperatingSystemVersion();
-#elif BUILDFLAG(IS_WIN)
-  base::win::OSInfo::VersionNumber version_number =
-      base::win::OSInfo::GetInstance()->version_number();
-  return base::StringPrintf("%d.%d.%d.%d", version_number.major,
-                            version_number.minor, version_number.build,
-                            version_number.patch);
-#else
-  NOTREACHED();
-  return std::string();
-#endif
-}
-
-std::string GetOSPlatform() {
-  return version_info::GetOSType();
-}
-
-std::unique_ptr<enterprise_management::BrowserDeviceIdentifier>
-GetBrowserDeviceIdentifier() {
-  std::unique_ptr<enterprise_management::BrowserDeviceIdentifier>
-      device_identifier =
-          std::make_unique<enterprise_management::BrowserDeviceIdentifier>();
-  device_identifier->set_computer_name(GetMachineName());
-#if BUILDFLAG(IS_WIN)
-  device_identifier->set_serial_number(base::WideToUTF8(
-      base::win::WmiComputerSystemInfo::Get().serial_number()));
-#else
-  device_identifier->set_serial_number("");
-#endif
-  return device_identifier;
-}
-
-}  // namespace policy
-
-}  // namespace updater
diff --git a/chrome/updater/device_management/cloud_policy_util.h b/chrome/updater/device_management/cloud_policy_util.h
deleted file mode 100644
index 4dd49e91..0000000
--- a/chrome/updater/device_management/cloud_policy_util.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Code in this file are branched from
-// components/policy/core/common/cloud/cloud_policy_constants.h and
-// components/policy/core/common/cloud/cloud_policy_util.h. See the
-// TODO comment below.
-
-#ifndef CHROME_UPDATER_DEVICE_MANAGEMENT_CLOUD_POLICY_UTIL_H_
-#define CHROME_UPDATER_DEVICE_MANAGEMENT_CLOUD_POLICY_UTIL_H_
-
-#include <memory>
-#include <string>
-
-namespace enterprise_management {
-class BrowserDeviceIdentifier;
-}
-
-namespace updater {
-
-namespace policy {
-// Implementations in this namespace are copied from //components/policy.
-// TODO(crbug.com/1219760): Remove this namespace and reuse code from
-// //components/policy.
-extern const char kPolicyVerificationKeyHash[];
-
-std::string GetPolicyVerificationKey();
-std::string GetMachineName();
-std::string GetOSVersion();
-std::string GetOSPlatform();
-std::unique_ptr<enterprise_management::BrowserDeviceIdentifier>
-GetBrowserDeviceIdentifier();
-}  // namespace policy
-
-}  // namespace updater
-
-#endif  // CHROME_UPDATER_DEVICE_MANAGEMENT_CLOUD_POLICY_UTIL_H_
diff --git a/chrome/updater/device_management/dm_message.cc b/chrome/updater/device_management/dm_message.cc
index 660d7f66..c09b975 100644
--- a/chrome/updater/device_management/dm_message.cc
+++ b/chrome/updater/device_management/dm_message.cc
@@ -9,8 +9,9 @@
 
 #include "base/containers/fixed_flat_map.h"
 #include "base/logging.h"
-#include "chrome/updater/device_management/cloud_policy_util.h"
 #include "chrome/updater/device_management/dm_response_validator.h"
+#include "components/policy/core/common/cloud/cloud_policy_constants.h"
+#include "components/policy/core/common/cloud/cloud_policy_util.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 
 namespace updater {
diff --git a/chrome/updater/device_management/dm_response_validator.cc b/chrome/updater/device_management/dm_response_validator.cc
index 47810ab..a5617ba5 100644
--- a/chrome/updater/device_management/dm_response_validator.cc
+++ b/chrome/updater/device_management/dm_response_validator.cc
@@ -16,10 +16,10 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/updater/constants.h"
-#include "chrome/updater/device_management/cloud_policy_util.h"
 #include "chrome/updater/device_management/dm_cached_policy_info.h"
 #include "chrome/updater/device_management/dm_message.h"
 #include "chrome/updater/protos/omaha_settings.pb.h"
+#include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "crypto/signature_verifier.h"
 #include "third_party/boringssl/src/include/openssl/rsa.h"
diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS
index faf3971..ae19ae0 100644
--- a/chrome/utility/DEPS
+++ b/chrome/utility/DEPS
@@ -36,6 +36,7 @@
   "+chromeos/services/libassistant/libassistant_service.h",
   "+chromeos/services/tts",
   "+components/crash/core/common/crash_keys.h",
+  "+components/device_signals/core/common/mojom",
   "+components/mirroring/mojom",
   "+components/mirroring/service",
   "+components/paint_preview/buildflags",
diff --git a/chrome/utility/services.cc b/chrome/utility/services.cc
index 3df8b91e..85ccea70 100644
--- a/chrome/utility/services.cc
+++ b/chrome/utility/services.cc
@@ -35,13 +35,13 @@
 #endif
 
 #if BUILDFLAG(IS_WIN)
-#include "chrome/services/system_signals/public/mojom/system_signals.mojom.h"
 #include "chrome/services/system_signals/win/win_system_signals_service.h"
 #include "chrome/services/util_win/processor_metrics.h"
 #include "chrome/services/util_win/public/mojom/util_read_icon.mojom.h"
 #include "chrome/services/util_win/public/mojom/util_win.mojom.h"
 #include "chrome/services/util_win/util_read_icon.h"
 #include "chrome/services/util_win/util_win_impl.h"
+#include "components/device_signals/core/common/mojom/system_signals.mojom.h"
 #include "components/services/quarantine/public/mojom/quarantine.mojom.h"  // nogncheck
 #include "components/services/quarantine/quarantine_impl.h"  // nogncheck
 #include "services/proxy_resolver_win/public/mojom/proxy_resolver_win.mojom.h"
@@ -175,7 +175,7 @@
 }
 
 auto RunSystemSignalsService(
-    mojo::PendingReceiver<system_signals::mojom::SystemSignalsService>
+    mojo::PendingReceiver<device_signals::mojom::SystemSignalsService>
         receiver) {
   return std::make_unique<system_signals::WinSystemSignalsService>(
       std::move(receiver));
diff --git a/chromecast/browser/cast_permission_manager.cc b/chromecast/browser/cast_permission_manager.cc
index cd9f06b..8dc88916 100644
--- a/chromecast/browser/cast_permission_manager.cc
+++ b/chromecast/browser/cast_permission_manager.cc
@@ -152,6 +152,21 @@
                                             const GURL& requesting_origin,
                                             const GURL& embedding_origin) {}
 
+void CastPermissionManager::RequestPermissionsFromCurrentDocument(
+    const std::vector<blink::PermissionType>& permissions,
+    content::RenderFrameHost* render_frame_host,
+    bool user_gesture,
+    base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
+        callback) {
+  std::vector<blink::mojom::PermissionStatus> permission_statuses;
+  for (auto permission : permissions) {
+    permission_statuses.push_back(GetPermissionStatusInternal(
+        permission, render_frame_host,
+        render_frame_host->GetLastCommittedOrigin().GetURL()));
+  }
+  std::move(callback).Run(permission_statuses);
+}
+
 blink::mojom::PermissionStatus CastPermissionManager::GetPermissionStatus(
     blink::PermissionType permission,
     const GURL& requesting_origin,
@@ -160,15 +175,6 @@
 }
 
 blink::mojom::PermissionStatus
-CastPermissionManager::GetPermissionStatusForFrame(
-    blink::PermissionType permission,
-    content::RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin) {
-  return GetPermissionStatusInternal(permission, render_frame_host,
-                                     requesting_origin);
-}
-
-blink::mojom::PermissionStatus
 CastPermissionManager::GetPermissionStatusForCurrentDocument(
     blink::PermissionType permission,
     content::RenderFrameHost* render_frame_host) {
diff --git a/chromecast/browser/cast_permission_manager.h b/chromecast/browser/cast_permission_manager.h
index cf3597d..7fac9e2 100644
--- a/chromecast/browser/cast_permission_manager.h
+++ b/chromecast/browser/cast_permission_manager.h
@@ -45,14 +45,17 @@
   void ResetPermission(blink::PermissionType permission,
                        const GURL& requesting_origin,
                        const GURL& embedding_origin) override;
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<
+          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+      override;
   blink::mojom::PermissionStatus GetPermissionStatus(
       blink::PermissionType permission,
       const GURL& requesting_origin,
       const GURL& embedding_origin) override;
-  blink::mojom::PermissionStatus GetPermissionStatusForFrame(
-      blink::PermissionType permission,
-      content::RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin) override;
   blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
       blink::PermissionType permission,
       content::RenderFrameHost* render_frame_host) override;
diff --git a/chromecast/crash/linux/crash_testing_utils.cc b/chromecast/crash/linux/crash_testing_utils.cc
index dfd65268..bd822216 100644
--- a/chromecast/crash/linux/crash_testing_utils.cc
+++ b/chromecast/crash/linux/crash_testing_utils.cc
@@ -50,7 +50,7 @@
     RCHECK(dump_info.has_value(), nullptr, "Invalid DumpInfo");
     DumpInfo info(&dump_info.value());
     RCHECK(info.valid(), nullptr, "Invalid DumpInfo");
-    dumps->Append(std::move(dump_info.value()));
+    dumps->GetList().Append(std::move(dump_info.value()));
   }
 
   return dumps;
@@ -149,7 +149,8 @@
     }
   }
 
-  contents->Append(dump.GetAsValue());
+  contents->GetList().Append(
+      base::Value::FromUniquePtrValue(dump.GetAsValue()));
 
   return WriteLockFile(lockfile_path, contents.get()) == 0;
 }
diff --git a/chromecast/crash/linux/synchronized_minidump_manager.cc b/chromecast/crash/linux/synchronized_minidump_manager.cc
index b705883..b0b1056c 100644
--- a/chromecast/crash/linux/synchronized_minidump_manager.cc
+++ b/chromecast/crash/linux/synchronized_minidump_manager.cc
@@ -303,7 +303,7 @@
     RCHECK(dump_info.has_value(), false);
     DumpInfo info(&dump_info.value());
     RCHECK(info.valid(), false);
-    dumps->Append(std::move(dump_info.value()));
+    dumps->GetList().Append(std::move(dump_info.value()));
   }
 
   JSONFileValueDeserializer deserializer(metadata_path_);
@@ -367,7 +367,8 @@
     return false;
   }
 
-  dumps_->Append(dump_info.GetAsValue());
+  dumps_->GetList().Append(
+      base::Value::FromUniquePtrValue(dump_info.GetAsValue()));
   return true;
 }
 
@@ -407,8 +408,10 @@
     const std::vector<std::unique_ptr<DumpInfo>>& dumps) {
   dumps_->ClearList();
 
-  for (auto& dump : dumps)
-    dumps_->Append(dump->GetAsValue());
+  for (auto& dump : dumps) {
+    dumps_->GetList().Append(
+        base::Value::FromUniquePtrValue(dump->GetAsValue()));
+  }
 
   return true;
 }
diff --git a/chromecast/tools/build/package_test_deps.py b/chromecast/tools/build/package_test_deps.py
index 68ee1d3..45f5454c 100755
--- a/chromecast/tools/build/package_test_deps.py
+++ b/chromecast/tools/build/package_test_deps.py
@@ -84,7 +84,7 @@
   with tarfile.open(output_path, 'w:gz') as tar_file:
     for idx, dep in enumerate(dependencies):
       dep = os.path.normpath(dep)
-      archive_name = os.path.join('fuchsia/release', dep)
+      archive_name = os.path.join('tools/fuchsia/size_tests', dep)
       archive_name = os.path.normpath(archive_name)
       tar_file.add(dep, arcname=archive_name)
       if idx % step == 0 or idx == (total_deps - 1):
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom
index 88cda1b..b6a2d09 100644
--- a/chromeos/crosapi/mojom/crosapi.mojom
+++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -596,8 +596,8 @@
 };
 
 // The device specific data needed in Lacros.
-// Next version: 2
-// Next id: 2
+// Next version: 3
+// Next id: 4
 // TODO(igorcov): Include DeviceAttributes here.
 [Stable]
 struct DeviceProperties {
@@ -610,6 +610,13 @@
   // determined. It is non-encrypted data corresponding to
   // PolicyData::device_affiliation_ids.
   [MinVersion=1] array<string>? device_affiliation_ids@1;
+
+  // Whether ARC is installed and the current device is officially supported to
+  // run ARC.
+  [MinVersion=2] bool is_arc_available@2;
+
+  // Whether the device is of tablet form factor.
+  [MinVersion=2] bool is_tablet_form_factor@3;
 };
 
 [Stable, Extensible]
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AssistantRootViewContainer.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AssistantRootViewContainer.java
index 1651d8ac..3c2456d 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AssistantRootViewContainer.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/AssistantRootViewContainer.java
@@ -51,14 +51,12 @@
     }
 
     @Override
-    public void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset,
-            int bottomOffset, int bottomControlsMinHeightOffset, boolean needsAnimate) {
+    public void onControlsOffsetChanged() {
         invalidate();
     }
 
     @Override
-    public void onBottomControlsHeightChanged(
-            int bottomControlsHeight, int bottomControlsMinHeight) {
+    public void onBottomControlsHeightChanged() {
         invalidate();
     }
 
diff --git a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/overlay/AssistantOverlayDrawable.java b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/overlay/AssistantOverlayDrawable.java
index 3cbc7c91..ac00366 100644
--- a/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/overlay/AssistantOverlayDrawable.java
+++ b/components/autofill_assistant/android/java/src/org/chromium/components/autofill_assistant/overlay/AssistantOverlayDrawable.java
@@ -377,14 +377,12 @@
     }
 
     @Override
-    public void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset,
-            int bottomOffset, int bottomControlsMinHeightOffset, boolean needsAnimate) {
+    public void onControlsOffsetChanged() {
         invalidateSelf();
     }
 
     @Override
-    public void onBottomControlsHeightChanged(
-            int bottomControlsHeight, int bottomControlsMinHeight) {
+    public void onBottomControlsHeightChanged() {
         invalidateSelf();
     }
 
diff --git a/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AssistantBrowserControls.java b/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AssistantBrowserControls.java
index 2066cf4..ca8cb04 100644
--- a/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AssistantBrowserControls.java
+++ b/components/autofill_assistant/android/public/java/src/org/chromium/components/autofill_assistant/AssistantBrowserControls.java
@@ -15,9 +15,8 @@
      * Observer for different browser control events.
      */
     public interface Observer {
-        void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset,
-                int bottomOffset, int bottomControlsMinHeightOffset, boolean needsAnimate);
-        void onBottomControlsHeightChanged(int bottomControlsHeight, int bottomControlsMinHeight);
+        void onControlsOffsetChanged();
+        void onBottomControlsHeightChanged();
     }
 
     void setObserver(Observer browserControlsObserver);
diff --git a/components/component_updater/component_updater_service.cc b/components/component_updater/component_updater_service.cc
index 33d6bee..6e0ca5d 100644
--- a/components/component_updater/component_updater_service.cc
+++ b/components/component_updater/component_updater_service.cc
@@ -367,52 +367,26 @@
   UMA_HISTOGRAM_ENUMERATION("ComponentUpdater.Calls", UPDATE_TYPE_AUTOMATIC,
                             UPDATE_TYPE_COUNT);
 
-  std::vector<std::string> secure_ids;    // Requires HTTPS for update checks.
-  std::vector<std::string> unsecure_ids;  // Can fallback to HTTP.
-  for (const auto& id : components_order_) {
-    DCHECK(components_.find(id) != components_.end());
-
-    const auto component = GetComponent(id);
-    if (!component || component->requires_network_encryption)
-      secure_ids.push_back(id);
-    else
-      unsecure_ids.push_back(id);
-  }
-
-  if (unsecure_ids.empty() && secure_ids.empty()) {
+  if (components_order_.empty()) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                   std::move(on_finished));
     return true;
   }
 
-  Callback on_finished_callback = base::BindOnce(
-      [](UpdateScheduler::OnFinishedCallback on_finished,
-         update_client::Error error) { std::move(on_finished).Run(); },
-      std::move(on_finished));
-
-  if (!unsecure_ids.empty()) {
-    update_client_->Update(
-        unsecure_ids,
-        base::BindOnce(&CrxUpdateService::GetCrxComponents,
-                       base::Unretained(this)),
-        {}, false,
-        base::BindOnce(
-            &CrxUpdateService::OnUpdateComplete, base::Unretained(this),
-            secure_ids.empty() ? std::move(on_finished_callback) : Callback(),
-            base::TimeTicks::Now()));
-  }
-
-  if (!secure_ids.empty()) {
-    update_client_->Update(
-        secure_ids,
-        base::BindOnce(&CrxUpdateService::GetCrxComponents,
-                       base::Unretained(this)),
-        {}, false,
-        base::BindOnce(&CrxUpdateService::OnUpdateComplete,
-                       base::Unretained(this), std::move(on_finished_callback),
-                       base::TimeTicks::Now()));
-  }
-
+  update_client_->Update(
+      components_order_,
+      base::BindOnce(&CrxUpdateService::GetCrxComponents,
+                     base::Unretained(this)),
+      {}, false,
+      base::BindOnce(&CrxUpdateService::OnUpdateComplete,
+                     base::Unretained(this),
+                     base::BindOnce(
+                         [](UpdateScheduler::OnFinishedCallback on_finished,
+                            update_client::Error /*error*/) {
+                           std::move(on_finished).Run();
+                         },
+                         std::move(on_finished)),
+                     base::TimeTicks::Now()));
   return true;
 }
 
diff --git a/components/crash/core/app/crashpad_ios.mm b/components/crash/core/app/crashpad_ios.mm
index d3db34c..83d13ef4 100644
--- a/components/crash/core/app/crashpad_ios.mm
+++ b/components/crash/core/app/crashpad_ios.mm
@@ -166,7 +166,10 @@
   @autoreleasepool {
     CrashReporterClient* crash_reporter_client = GetCrashReporterClient();
     crash_reporter_client->GetCrashDumpLocation(database_path);
-    std::string url = crash_reporter_client->GetUploadUrl();
+    // Don't pass `url` to extensions since they never upload minidumps.
+    std::string url = [NSBundle.mainBundle.bundlePath hasSuffix:@"appex"]
+                          ? ""
+                          : crash_reporter_client->GetUploadUrl();
     return GetCrashpadClient().StartCrashpadInProcessHandler(
         *database_path, url, GetProcessSimpleAnnotations());
   }  // @autoreleasepool
diff --git a/chrome/services/system_signals/public/mojom/BUILD.gn b/components/device_signals/core/common/mojom/BUILD.gn
similarity index 100%
rename from chrome/services/system_signals/public/mojom/BUILD.gn
rename to components/device_signals/core/common/mojom/BUILD.gn
diff --git a/chrome/services/system_signals/public/mojom/OWNERS b/components/device_signals/core/common/mojom/OWNERS
similarity index 100%
rename from chrome/services/system_signals/public/mojom/OWNERS
rename to components/device_signals/core/common/mojom/OWNERS
diff --git a/chrome/services/system_signals/public/mojom/system_signals.mojom b/components/device_signals/core/common/mojom/system_signals.mojom
similarity index 98%
rename from chrome/services/system_signals/public/mojom/system_signals.mojom
rename to components/device_signals/core/common/mojom/system_signals.mojom
index 51871d6..6bdccd9 100644
--- a/chrome/services/system_signals/public/mojom/system_signals.mojom
+++ b/components/device_signals/core/common/mojom/system_signals.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-module system_signals.mojom;
+module device_signals.mojom;
 
 import "mojo/public/mojom/base/file_path.mojom";
 import "sandbox/policy/mojom/sandbox.mojom";
diff --git a/components/feed/core/proto/BUILD.gn b/components/feed/core/proto/BUILD.gn
index 59e042d2..480767a 100644
--- a/components/feed/core/proto/BUILD.gn
+++ b/components/feed/core/proto/BUILD.gn
@@ -39,6 +39,7 @@
     "v2/wire/feed_action.proto",
     "v2/wire/feed_entry_point_data.proto",
     "v2/wire/feed_entry_point_source.proto",
+    "v2/wire/feed_preferences.proto",
     "v2/wire/feed_query.proto",
     "v2/wire/feed_request.proto",
     "v2/wire/feed_response.proto",
diff --git a/components/feed/core/proto/v2/wire/capability.proto b/components/feed/core/proto/v2/wire/capability.proto
index d4bf141..e1a10fcb 100644
--- a/components/feed/core/proto/v2/wire/capability.proto
+++ b/components/feed/core/proto/v2/wire/capability.proto
@@ -38,4 +38,5 @@
   ON_DEVICE_USER_PROFILE = 70;
   INVALIDATE_CACHE_COMMAND = 73;
   INFO_CARD_ACKNOWLEDGEMENT_TRACKING = 77;
+  THANK_CREATOR = 79;
 }
diff --git a/components/feed/core/proto/v2/wire/client_info.proto b/components/feed/core/proto/v2/wire/client_info.proto
index a203639..fb774c0 100644
--- a/components/feed/core/proto/v2/wire/client_info.proto
+++ b/components/feed/core/proto/v2/wire/client_info.proto
@@ -19,7 +19,9 @@
     ANDROID_ID = 1;
     IOS = 2;
   }
-  enum AppType { CHROME_ANDROID = 3; }
+  enum AppType {
+    CHROME_ANDROID = 3;
+  }
   optional PlatformType platform_type = 1;
   optional Version platform_version = 2;
   optional AppType app_type = 3;
diff --git a/components/feed/core/proto/v2/wire/client_user_profiles.proto b/components/feed/core/proto/v2/wire/client_user_profiles.proto
index 674dc6c..30f33572 100644
--- a/components/feed/core/proto/v2/wire/client_user_profiles.proto
+++ b/components/feed/core/proto/v2/wire/client_user_profiles.proto
@@ -10,6 +10,7 @@
 
 message ClientUserProfiles {
   optional DiscoverUserActionsProfile discover_user_actions_profile = 1;
+  optional ViewDemotionProfile view_demotion_profile = 2;
 }
 message ActionCounts {
   message Counts {
@@ -26,6 +27,7 @@
 }
 message DiscoverUserActionsProfile {
   message ContentMediaXEntityActionCounts {
+    optional uint64 content_category_media_type = 1;
     optional uint64 mid = 2;
     repeated ActionCounts counts = 3;
   }
@@ -37,3 +39,4 @@
   repeated ContentMediaXEntityActionCounts content_media_x_entity = 2;
   repeated CardCategoryXEntityActionCounts card_category_x_entity = 3;
 }
+message ViewDemotionProfile {}
diff --git a/components/feed/core/proto/v2/wire/feed_preferences.proto b/components/feed/core/proto/v2/wire/feed_preferences.proto
new file mode 100644
index 0000000..670e09c8
--- /dev/null
+++ b/components/feed/core/proto/v2/wire/feed_preferences.proto
@@ -0,0 +1,17 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+package feedwire;
+
+option optimize_for = LITE_RUNTIME;
+
+message FeedPreferences {
+  enum FeedType {
+    FEED_TYPE_UNSPECIFIED = 0;
+    FEED_TYPE_VISUAL = 1;
+  }
+  optional FeedType feed_type = 1;
+}
diff --git a/components/feed/core/proto/v2/wire/feed_query.proto b/components/feed/core/proto/v2/wire/feed_query.proto
index 4f0f021f..1dd00e4c 100644
--- a/components/feed/core/proto/v2/wire/feed_query.proto
+++ b/components/feed/core/proto/v2/wire/feed_query.proto
@@ -8,12 +8,15 @@
 
 import "components/feed/core/proto/v2/wire/chrome_fulfillment_info.proto";
 import "components/feed/core/proto/v2/wire/feed_entry_point_data.proto";
+import "components/feed/core/proto/v2/wire/feed_preferences.proto";
 import "components/feed/core/proto/v2/wire/token.proto";
 
 option optimize_for = LITE_RUNTIME;
 
 message FeedQuery {
-  message Tokens { repeated Token tokens = 1; }
+  message Tokens {
+    repeated Token tokens = 1;
+  }
   enum RequestReason {
     UNKNOWN_REQUEST_REASON = 0;
     MANUAL_REFRESH = 1;
@@ -35,4 +38,5 @@
   optional ContentOrder order_by = 8;
   optional FeedEntryPointData feed_entry_point_data = 9;
   optional ChromeFulfillmentInfo chrome_fulfillment_info = 341477699;
+  optional FeedPreferences feed_preferences = 445876180;
 }
diff --git a/components/feed/core/proto/v2/wire/request_schedule.proto b/components/feed/core/proto/v2/wire/request_schedule.proto
index 2832031..9c80e76a 100644
--- a/components/feed/core/proto/v2/wire/request_schedule.proto
+++ b/components/feed/core/proto/v2/wire/request_schedule.proto
@@ -14,5 +14,7 @@
   message TimeBasedSchedule {
     repeated Duration refresh_time_from_response_time = 1;
   }
-  oneof schedule { TimeBasedSchedule time_based_schedule = 1; }
+  oneof schedule {
+    TimeBasedSchedule time_based_schedule = 1;
+  }
 }
diff --git a/components/feed/core/proto/v2/wire/web_feeds.proto b/components/feed/core/proto/v2/wire/web_feeds.proto
index b404d74b..0f108807 100644
--- a/components/feed/core/proto/v2/wire/web_feeds.proto
+++ b/components/feed/core/proto/v2/wire/web_feeds.proto
@@ -11,6 +11,14 @@
 
 option optimize_for = LITE_RUNTIME;
 
+enum WebFeedChangeReason {
+  WEB_FEED_CHANGE_REASON_UNSPECIFIED = 0;
+  WEB_PAGE_MENU = 1;
+  WEB_PAGE_ACCELERATOR = 2;
+  MANAGEMENT = 3;
+  IN_FEED_RECOMMENDATION = 4;
+  BACK_OF_CARD_UNFOLLOW = 5;
+}
 message WebFeed {
   enum State {
     STATE_UNSPECIFIED = 0;
@@ -46,6 +54,7 @@
   string canonical_uri = 5;
   repeated string page_rss_uris = 3;
   ConsistencyToken consistency_token = 4;
+  WebFeedChangeReason change_reason = 6;
 }
 message FollowWebFeedResponse {
   WebFeed web_feed = 1;
@@ -54,6 +63,7 @@
 message UnfollowWebFeedRequest {
   string name = 1;
   ConsistencyToken consistency_token = 2;
+  WebFeedChangeReason change_reason = 3;
 }
 message UnfollowWebFeedResponse {
   ConsistencyToken consistency_token = 1;
diff --git a/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h b/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h
index a0191012..521703e5 100644
--- a/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h
+++ b/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h
@@ -13,6 +13,7 @@
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/scoped_visibility_tracker.h"
+#include "url/gurl.h"
 
 namespace content {
 class WebContents;
diff --git a/components/page_load_metrics/common/page_load_metrics.mojom b/components/page_load_metrics/common/page_load_metrics.mojom
index 7192cf46..da3b279d 100644
--- a/components/page_load_metrics/common/page_load_metrics.mojom
+++ b/components/page_load_metrics/common/page_load_metrics.mojom
@@ -11,7 +11,6 @@
 import
   "third_party/blink/public/mojom/mobile_metrics/mobile_friendliness.mojom";
 import "third_party/blink/public/mojom/use_counter/use_counter_feature.mojom";
-import "url/mojom/origin.mojom";
 
 // TimeDeltas below relative to navigation start.
 struct DocumentTiming {
@@ -262,9 +261,6 @@
   // Whether this resource was fetched via proxy.
   bool proxy_used;
 
-  // The origin of this resource.
-  url.mojom.Origin origin;
-
   // Whether this resource completed loading, either by network or cache, before
   // FCP in the frame it belongs to. This flag can be set to true at any point
   // during a resource load. A more recent ResourceDataUpdate can have a
diff --git a/components/page_load_metrics/renderer/page_resource_data_use.cc b/components/page_load_metrics/renderer/page_resource_data_use.cc
index 8d30de0..5dc14f6 100644
--- a/components/page_load_metrics/renderer/page_resource_data_use.cc
+++ b/components/page_load_metrics/renderer/page_resource_data_use.cc
@@ -43,7 +43,6 @@
   is_secure_scheme_ = response_url.SchemeIsCryptographic();
   is_primary_frame_resource_ =
       blink::IsRequestDestinationFrame(request_destination);
-  origin_ = url::Origin::Create(response_url);
 }
 
 void PageResourceDataUse::DidReceiveTransferSizeUpdate(
@@ -71,7 +70,6 @@
                                                  int request_id,
                                                  int64_t encoded_body_length,
                                                  const std::string& mime_type) {
-  origin_ = url::Origin::Create(response_url);
   resource_id_ = request_id;
   mime_type_ = mime_type;
   is_secure_scheme_ = response_url.SchemeIsCryptographic();
@@ -126,7 +124,6 @@
   resource_data_update->is_secure_scheme = is_secure_scheme_;
   resource_data_update->proxy_used = proxy_used_;
   resource_data_update->is_primary_frame_resource = is_primary_frame_resource_;
-  resource_data_update->origin = origin_;
   resource_data_update->completed_before_fcp = completed_before_fcp_;
   return resource_data_update;
 }
diff --git a/components/page_load_metrics/renderer/page_resource_data_use.h b/components/page_load_metrics/renderer/page_resource_data_use.h
index 5b873ed..604b042 100644
--- a/components/page_load_metrics/renderer/page_resource_data_use.h
+++ b/components/page_load_metrics/renderer/page_resource_data_use.h
@@ -8,7 +8,6 @@
 #include "components/page_load_metrics/common/page_load_metrics.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
-#include "url/origin.h"
 
 class GURL;
 
@@ -89,8 +88,6 @@
 
   mojom::CacheType cache_type_;
 
-  url::Origin origin_;
-
   std::string mime_type_;
 };
 
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index 22e77d6..d9cddc1 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -255,6 +255,7 @@
 #if BUILDFLAG(IS_ANDROID)
   registry->RegisterBooleanPref(prefs::kOfferToSavePasswordsEnabledGMS, true);
   registry->RegisterBooleanPref(prefs::kAutoSignInEnabledGMS, true);
+  registry->RegisterBooleanPref(prefs::kSettingsMigratedToUPM, false);
   registry->RegisterIntegerPref(
       prefs::kCurrentMigrationVersionToGoogleMobileServices, 0);
   registry->RegisterDoublePref(prefs::kTimeOfLastMigrationAttempt, 0.0);
diff --git a/components/password_manager/core/browser/password_manager_features_util.cc b/components/password_manager/core/browser/password_manager_features_util.cc
index eed2bef8..33d166cd 100644
--- a/components/password_manager/core/browser/password_manager_features_util.cc
+++ b/components/password_manager/core/browser/password_manager_features_util.cc
@@ -19,7 +19,7 @@
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/sync/driver/sync_service.h"
 #include "components/sync/driver/sync_user_settings.h"
-#include "google_apis/gaia/gaia_urls.h"
+#include "google_apis/gaia/gaia_auth_util.h"
 
 using autofill::GaiaIdHash;
 using password_manager::metrics_util::PasswordAccountStorageUsageLevel;
@@ -224,8 +224,7 @@
     return false;
   }
 
-  if (current_page_url.DeprecatedGetOriginAsURL() ==
-      GaiaUrls::GetInstance()->gaia_url().DeprecatedGetOriginAsURL()) {
+  if (gaia::HasGaiaSchemeHostPort(current_page_url)) {
     return false;
   }
 
diff --git a/components/password_manager/core/browser/password_reuse_detector.cc b/components/password_manager/core/browser/password_reuse_detector.cc
index fc34aab9..bb517ec 100644
--- a/components/password_manager/core/browser/password_reuse_detector.cc
+++ b/components/password_manager/core/browser/password_reuse_detector.cc
@@ -17,10 +17,6 @@
 #include "components/password_manager/core/browser/psl_matching_helper.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "google_apis/gaia/gaia_auth_util.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "url/origin.h"
-
-using url::Origin;
 
 namespace password_manager {
 
@@ -195,9 +191,7 @@
   }
 
   // Skips password reuse check if |domain| matches Gaia origin.
-  const Origin gaia_origin = Origin::Create(
-      GaiaUrls::GetInstance()->gaia_url().DeprecatedGetOriginAsURL());
-  if (Origin::Create(GURL(domain)).IsSameOriginWith(gaia_origin))
+  if (gaia::HasGaiaSchemeHostPort(GURL(domain)))
     return absl::nullopt;
 
   return FindPasswordReuse(input, gaia_password_hash_data_list_.value());
diff --git a/components/password_manager/core/common/password_manager_pref_names.cc b/components/password_manager/core/common/password_manager_pref_names.cc
index d2b432a7..bdab31e 100644
--- a/components/password_manager/core/common/password_manager_pref_names.cc
+++ b/components/password_manager/core/common/password_manager_pref_names.cc
@@ -16,6 +16,7 @@
 const char kAutoSignInEnabledGMS[] = "profile.auto_sign_in_enabled_gms";
 const char kOfferToSavePasswordsEnabledGMS[] =
     "profile.save_passwords_enabed_gms";
+const char kSettingsMigratedToUPM[] = "profile.settings_migrated_to_upm";
 
 const char kCurrentMigrationVersionToGoogleMobileServices[] =
     "current_migration_version_to_google_mobile_services";
diff --git a/components/password_manager/core/common/password_manager_pref_names.h b/components/password_manager/core/common/password_manager_pref_names.h
index 600d5de..46e39a2 100644
--- a/components/password_manager/core/common/password_manager_pref_names.h
+++ b/components/password_manager/core/common/password_manager_pref_names.h
@@ -49,6 +49,10 @@
 // mapped to `kCredentialEnableService` will be applied.
 extern const char kOfferToSavePasswordsEnabledGMS[];
 
+// Boolean value indicating whether the regular prefs were migrated to UPM
+// settings.
+extern const char kSettingsMigratedToUPM[];
+
 // Integer value which indicates the version used to migrate passwords from
 // built in storage to Google Mobile Services.
 extern const char kCurrentMigrationVersionToGoogleMobileServices[];
diff --git a/components/permissions/DEPS b/components/permissions/DEPS
index 09033002..910209a 100644
--- a/components/permissions/DEPS
+++ b/components/permissions/DEPS
@@ -26,6 +26,7 @@
   "+third_party/blink/public/common/permissions/permission_utils.h",
   "+third_party/blink/public/common/web_preferences",
   "+third_party/blink/public/mojom/bluetooth",
+  "+third_party/blink/public/mojom/permissions/permission_status.mojom.h",
   "+third_party/blink/public/mojom/permissions_policy",
   "+third_party/blink/public/mojom/quota",
   "+third_party/sqlite",
diff --git a/components/permissions/permission_manager.cc b/components/permissions/permission_manager.cc
index ea2ad630..698d7a5d 100644
--- a/components/permissions/permission_manager.cc
+++ b/components/permissions/permission_manager.cc
@@ -73,21 +73,6 @@
   return PermissionStatus::DENIED;
 }
 
-ContentSetting PermissionStatusToContentSetting(PermissionStatus status) {
-  switch (status) {
-    case PermissionStatus::GRANTED:
-      return CONTENT_SETTING_ALLOW;
-    case PermissionStatus::ASK:
-      return CONTENT_SETTING_ASK;
-    case PermissionStatus::DENIED:
-    default:
-      return CONTENT_SETTING_BLOCK;
-  }
-
-  NOTREACHED();
-  return CONTENT_SETTING_DEFAULT;
-}
-
 PermissionDelegationMode GetPermissionDelegationMode(
     ContentSettingsType permission) {
   // TODO(crbug.com/987654): Generalize this to other "background permissions",
@@ -106,13 +91,6 @@
   std::move(callback).Run(ContentSettingToPermissionStatus(content_setting));
 }
 
-void PermissionStatusCallbackWrapper(
-    base::OnceCallback<void(PermissionStatus)> callback,
-    const std::vector<ContentSetting>& vector) {
-  DCHECK_EQ(1ul, vector.size());
-  std::move(callback).Run(ContentSettingToPermissionStatus(vector.at(0)));
-}
-
 void PermissionStatusVectorCallbackWrapper(
     base::OnceCallback<void(const std::vector<PermissionStatus>&)> callback,
     const std::vector<ContentSetting>& content_settings) {
@@ -123,17 +101,6 @@
   std::move(callback).Run(permission_statuses);
 }
 
-void ContentSettingCallbackWrapper(
-    base::OnceCallback<void(ContentSetting)> callback,
-    const std::vector<ContentSetting>& vector) {
-  DCHECK_EQ(1ul, vector.size());
-  std::move(callback).Run(vector.at(0));
-}
-
-// TODO(crbug.com/698985): As part of the permission API refactoring, this
-// method should be used in all places where we check or request permissions.
-// Currently it is used only in `RequestPermissions` and
-// `GetPermissionStatusForFrame`.
 GURL GetEmbeddingOrigin(content::RenderFrameHost* const render_frame_host,
                         const GURL& requesting_origin) {
   content::WebContents* const web_contents =
@@ -305,10 +272,6 @@
     ContentSettingsType permission,
     const GURL& requesting_origin,
     const GURL& embedding_origin) {
-  // With permission delegation enabled, this function should only ever be
-  // called for the top level origin (or a service worker origin).
-  // GetPermissionStatusForFrame should be called when to determine the status
-  // for an embedded frame.
   DCHECK_EQ(requesting_origin, embedding_origin);
 
   return GetPermissionStatusHelper(permission,
@@ -356,17 +319,6 @@
   }
 }
 
-void PermissionManager::RequestPermissionsFromCurrentDocument(
-    const std::vector<ContentSettingsType>& permissions,
-    content::RenderFrameHost* render_frame_host,
-    bool user_gesture,
-    base::OnceCallback<void(const std::vector<ContentSetting>&)> callback) {
-  RequestPermissions(
-      permissions, render_frame_host,
-      PermissionUtil::GetLastCommittedOriginAsURL(render_frame_host),
-      user_gesture, std::move(callback));
-}
-
 PermissionContextBase* PermissionManager::GetPermissionContextForTesting(
     ContentSettingsType type) {
   return GetPermissionContext(type);
@@ -378,25 +330,59 @@
   return it == permission_contexts_.end() ? nullptr : it->second.get();
 }
 
+// TODO(crbug.com/1271543): Remove
+// PermissionControllerDelegate::RequestPermission.
 void PermissionManager::RequestPermission(
-    ContentSettingsType content_settings_type,
+    PermissionType permission,
     content::RenderFrameHost* render_frame_host,
     const GURL& requesting_origin,
     bool user_gesture,
-    base::OnceCallback<void(ContentSetting)> callback) {
-  RequestPermissions(
-      std::vector<ContentSettingsType>(1, content_settings_type),
-      render_frame_host, requesting_origin, user_gesture,
-      base::BindOnce(&ContentSettingCallbackWrapper, std::move(callback)));
+    base::OnceCallback<void(PermissionStatus)> callback) {
+  NOTIMPLEMENTED();
 }
 
+// TODO(crbug.com/1271543): Remove
+// PermissionControllerDelegate::RequestPermissions.
 void PermissionManager::RequestPermissions(
-    const std::vector<ContentSettingsType>& permissions,
+    const std::vector<PermissionType>& permissions,
     content::RenderFrameHost* render_frame_host,
     const GURL& requesting_origin,
     bool user_gesture,
-    base::OnceCallback<void(const std::vector<ContentSetting>&)> callback) {
+    base::OnceCallback<void(const std::vector<PermissionStatus>&)> callback) {
+  NOTIMPLEMENTED();
+}
+
+void PermissionManager::ResetPermission(PermissionType permission,
+                                        const GURL& requesting_origin,
+                                        const GURL& embedding_origin) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  ContentSettingsType type =
+      PermissionUtil::PermissionTypeToContentSetting(permission);
+  PermissionContextBase* context = GetPermissionContext(type);
+  if (!context)
+    return;
+  context->ResetPermission(
+      GetCanonicalOrigin(type, requesting_origin, embedding_origin),
+      embedding_origin.DeprecatedGetOriginAsURL());
+}
+
+void PermissionManager::RequestPermissionsFromCurrentDocument(
+    const std::vector<PermissionType>& permissions_types,
+    content::RenderFrameHost* render_frame_host,
+    bool user_gesture,
+    base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
+        permission_status_callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  std::vector<ContentSettingsType> permissions;
+  std::transform(permissions_types.begin(), permissions_types.end(),
+                 back_inserter(permissions),
+                 PermissionUtil::PermissionTypeToContentSetting);
+
+  base::OnceCallback<void(const std::vector<ContentSetting>&)> callback =
+      base::BindOnce(&PermissionStatusVectorCallbackWrapper,
+                     std::move(permission_status_callback));
+
   if (permissions.empty()) {
     std::move(callback).Run(std::vector<ContentSetting>());
     return;
@@ -409,6 +395,8 @@
       request_local_id);
 
   const PermissionRequestID request_id(render_frame_host, request_local_id);
+  const GURL requesting_origin =
+      PermissionUtil::GetLastCommittedOriginAsURL(render_frame_host);
   const GURL embedding_origin =
       GetEmbeddingOrigin(render_frame_host, requesting_origin);
 
@@ -446,84 +434,6 @@
   }
 }
 
-void PermissionManager::RequestPermissionFromCurrentDocument(
-    ContentSettingsType content_settings_type,
-    content::RenderFrameHost* render_frame_host,
-    bool user_gesture,
-    base::OnceCallback<void(ContentSetting)> callback) {
-  RequestPermissionsFromCurrentDocument(
-      std::vector<ContentSettingsType>(1, content_settings_type),
-      render_frame_host, user_gesture,
-      base::BindOnce(&ContentSettingCallbackWrapper, std::move(callback)));
-}
-
-PermissionResult PermissionManager::GetPermissionStatusForFrame(
-    ContentSettingsType permission,
-    content::RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin) {
-  const GURL embedding_origin =
-      GetEmbeddingOrigin(render_frame_host, requesting_origin);
-
-  return GetPermissionStatusHelper(permission,
-                                   /*render_process_host=*/nullptr,
-                                   render_frame_host, requesting_origin,
-                                   embedding_origin);
-}
-
-PermissionResult PermissionManager::GetPermissionStatusForWorker(
-    ContentSettingsType permission,
-    content::RenderProcessHost* render_process_host,
-    const url::Origin& worker_origin) {
-  GURL worker_url = worker_origin.GetURL();
-  return GetPermissionStatusHelper(permission, render_process_host,
-                                   /*render_frame_host=*/nullptr, worker_url,
-                                   worker_url);
-}
-
-void PermissionManager::RequestPermission(
-    PermissionType permission,
-    content::RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin,
-    bool user_gesture,
-    base::OnceCallback<void(PermissionStatus)> callback) {
-  ContentSettingsType content_settings_type =
-      PermissionUtil::PermissionTypeToContentSetting(permission);
-  RequestPermissions(
-      std::vector<ContentSettingsType>(1, content_settings_type),
-      render_frame_host, requesting_origin, user_gesture,
-      base::BindOnce(&PermissionStatusCallbackWrapper, std::move(callback)));
-}
-
-void PermissionManager::RequestPermissions(
-    const std::vector<PermissionType>& permissions,
-    content::RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin,
-    bool user_gesture,
-    base::OnceCallback<void(const std::vector<PermissionStatus>&)> callback) {
-  std::vector<ContentSettingsType> content_settings_types;
-  std::transform(permissions.begin(), permissions.end(),
-                 back_inserter(content_settings_types),
-                 PermissionUtil::PermissionTypeToContentSetting);
-  RequestPermissions(content_settings_types, render_frame_host,
-                     requesting_origin, user_gesture,
-                     base::BindOnce(&PermissionStatusVectorCallbackWrapper,
-                                    std::move(callback)));
-}
-
-void PermissionManager::ResetPermission(PermissionType permission,
-                                        const GURL& requesting_origin,
-                                        const GURL& embedding_origin) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  ContentSettingsType type =
-      PermissionUtil::PermissionTypeToContentSetting(permission);
-  PermissionContextBase* context = GetPermissionContext(type);
-  if (!context)
-    return;
-  context->ResetPermission(
-      GetCanonicalOrigin(type, requesting_origin, embedding_origin),
-      embedding_origin.DeprecatedGetOriginAsURL());
-}
-
 PermissionStatus PermissionManager::GetPermissionStatus(
     PermissionType permission,
     const GURL& requesting_origin,
@@ -538,26 +448,24 @@
   return ContentSettingToPermissionStatus(result.content_setting);
 }
 
-PermissionStatus PermissionManager::GetPermissionStatusForFrame(
-    PermissionType permission,
-    content::RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin) {
-  // TODO(benwells): split this into two functions, GetPermissionStatus and
-  // GetPermissionStatusForPermissionsAPI.
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  ContentSettingsType type =
-      PermissionUtil::PermissionTypeToContentSetting(permission);
-  PermissionResult result =
-      GetPermissionStatusForFrame(type, render_frame_host, requesting_origin);
-  return ContentSettingToPermissionStatus(result.content_setting);
-}
-
 PermissionStatus PermissionManager::GetPermissionStatusForCurrentDocument(
     PermissionType permission,
     content::RenderFrameHost* render_frame_host) {
-  return GetPermissionStatusForFrame(
-      permission, render_frame_host,
-      PermissionUtil::GetLastCommittedOriginAsURL(render_frame_host));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  ContentSettingsType type =
+      PermissionUtil::PermissionTypeToContentSetting(permission);
+
+  const GURL requesting_origin =
+      PermissionUtil::GetLastCommittedOriginAsURL(render_frame_host);
+  const GURL embedding_origin =
+      GetEmbeddingOrigin(render_frame_host, requesting_origin);
+
+  PermissionResult result = GetPermissionStatusHelper(
+      type,
+      /*render_process_host=*/nullptr, render_frame_host, requesting_origin,
+      embedding_origin);
+
+  return ContentSettingToPermissionStatus(result.content_setting);
 }
 
 PermissionStatus PermissionManager::GetPermissionStatusForWorker(
@@ -567,8 +475,9 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   ContentSettingsType type =
       PermissionUtil::PermissionTypeToContentSetting(permission);
-  PermissionResult result = GetPermissionStatusForWorker(
-      type, render_process_host, url::Origin::Create(worker_origin));
+  PermissionResult result = GetPermissionStatusHelper(
+      type, render_process_host,
+      /*render_frame_host=*/nullptr, worker_origin, worker_origin);
 
   return ContentSettingToPermissionStatus(result.content_setting);
 }
@@ -620,17 +529,21 @@
     subscription->render_frame_id = render_frame_host->GetRoutingID();
     subscription->render_process_id = render_frame_host->GetProcess()->GetID();
     subscription->current_value =
-        GetPermissionStatusForFrame(content_type, render_frame_host,
-                                    requesting_origin)
+        GetPermissionStatusHelper(content_type,
+                                  /*render_process_host=*/nullptr,
+                                  render_frame_host, requesting_origin,
+                                  embedding_origin)
             .content_setting;
+
   } else {
     embedding_origin = requesting_origin;
     subscription->render_frame_id = -1;
     subscription->render_process_id =
         render_process_host ? render_process_host->GetID() : -1;
     subscription->current_value =
-        GetPermissionStatusForWorker(content_type, render_process_host,
-                                     url::Origin::Create(requesting_origin))
+        GetPermissionStatusHelper(content_type, render_process_host,
+                                  /*render_frame_host=*/nullptr,
+                                  requesting_origin, embedding_origin)
             .content_setting;
   }
 
@@ -718,26 +631,15 @@
     }
 
     content::RenderProcessHost* rph =
-        content::RenderProcessHost::FromID(subscription->render_process_id);
+        rfh ? nullptr
+            : content::RenderProcessHost::FromID(
+                  subscription->render_process_id);
 
-    ContentSetting new_value;
-    if (rfh) {
-      new_value = GetPermissionStatusForFrame(subscription->permission, rfh,
-                                              subscription->requesting_origin)
-                      .content_setting;
-    } else if (rph) {
-      new_value = GetPermissionStatusForWorker(
-                      subscription->permission, rph,
-                      url::Origin::Create(subscription->requesting_origin))
-                      .content_setting;
-    } else {
-      new_value = GetPermissionStatusHelper(subscription->permission,
-                                            /*render_process_host=*/nullptr,
-                                            /*render_frame_host=*/nullptr,
-                                            subscription->requesting_origin,
-                                            subscription->requesting_origin)
-                      .content_setting;
-    }
+    ContentSetting new_value =
+        GetPermissionStatusHelper(subscription->permission, rph, rfh,
+                                  subscription->requesting_origin,
+                                  embedding_origin)
+            .content_setting;
 
     if (subscription->current_value == new_value)
       continue;
@@ -812,7 +714,8 @@
     ContentSettingsType content_setting =
         PermissionUtil::PermissionTypeToContentSettingSafe(item.first);
     if (content_setting != ContentSettingsType::DEFAULT)
-      result[content_setting] = PermissionStatusToContentSetting(item.second);
+      result[content_setting] =
+          PermissionUtil::PermissionStatusToContentSetting(item.second);
   }
   const url::Origin& origin =
       optional_origin.value_or(devtools_global_overrides_origin_);
diff --git a/components/permissions/permission_manager.h b/components/permissions/permission_manager.h
index b40540c..bace981 100644
--- a/components/permissions/permission_manager.h
+++ b/components/permissions/permission_manager.h
@@ -94,15 +94,6 @@
   // KeyedService implementation.
   void Shutdown() override;
 
-  // Requests the given `permission` on behalf of the last committed document in
-  // `render_frame_host`, also performing additional checks such as Permission
-  // Policy.
-  void RequestPermissionsFromCurrentDocument(
-      const std::vector<ContentSettingsType>& permissions,
-      content::RenderFrameHost* render_frame_host,
-      bool user_gesture,
-      base::OnceCallback<void(const std::vector<ContentSetting>&)> callback);
-
   PermissionContextBase* GetPermissionContextForTesting(
       ContentSettingsType type);
 
@@ -133,48 +124,6 @@
 
   PermissionContextBase* GetPermissionContext(ContentSettingsType type);
 
-  // Callers from within chrome/ should use the methods which take the
-  // ContentSettingsType enum. The methods which take PermissionType values
-  // are for the content::PermissionControllerDelegate overrides and shouldn't
-  // be used from chrome/.
-  // Deprecated. Use `RequestPermissionFromCurrentDocument` instead.
-  void RequestPermission(ContentSettingsType permission,
-                         content::RenderFrameHost* render_frame_host,
-                         const GURL& requesting_origin,
-                         bool user_gesture,
-                         base::OnceCallback<void(ContentSetting)> callback);
-
-  // Deprecated. Use `RequestPermissionsFromCurrentDocument` instead.
-  void RequestPermissions(
-      const std::vector<ContentSettingsType>& permissions,
-      content::RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin,
-      bool user_gesture,
-      base::OnceCallback<void(const std::vector<ContentSetting>&)> callback);
-  void RequestPermissionFromCurrentDocument(
-      ContentSettingsType permission,
-      content::RenderFrameHost* render_frame_host,
-      bool user_gesture,
-      base::OnceCallback<void(ContentSetting)> callback);
-  // Returns the permission status for a given frame. This should be preferred
-  // over GetPermissionStatus as additional checks can be performed when we know
-  // the exact context the request is coming from.
-  // TODO(raymes): Currently we still pass the |requesting_origin| as a separate
-  // parameter because we can't yet guarantee that it matches the last committed
-  // origin of the RenderFrameHost. See crbug.com/698985.
-  // Deprecated. Use `GetPermissionStatusForCurrentDocument` instead.
-  PermissionResult GetPermissionStatusForFrame(
-      ContentSettingsType permission,
-      content::RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin);
-
-  // Returns the status of the given `permission` for a worker on `origin`
-  // running in the renderer corresponding to `render_process_host`.
-  PermissionResult GetPermissionStatusForWorker(
-      ContentSettingsType permission,
-      content::RenderProcessHost* render_process_host,
-      const url::Origin& worker_origin);
-
   // content::PermissionControllerDelegate implementation.
   void RequestPermission(
       blink::PermissionType permission,
@@ -194,14 +143,17 @@
   void ResetPermission(blink::PermissionType permission,
                        const GURL& requesting_origin,
                        const GURL& embedding_origin) override;
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<
+          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+      override;
   blink::mojom::PermissionStatus GetPermissionStatus(
       blink::PermissionType permission,
       const GURL& requesting_origin,
       const GURL& embedding_origin) override;
-  blink::mojom::PermissionStatus GetPermissionStatusForFrame(
-      blink::PermissionType permission,
-      content::RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin) override;
   blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
       blink::PermissionType permission,
       content::RenderFrameHost* render_frame_host) override;
diff --git a/components/permissions/permission_manager_unittest.cc b/components/permissions/permission_manager_unittest.cc
index d9b97770..6e7dd6c 100644
--- a/components/permissions/permission_manager_unittest.cc
+++ b/components/permissions/permission_manager_unittest.cc
@@ -138,25 +138,38 @@
                                                                type, value);
   }
 
-  void RequestPermission(PermissionType type,
-                         content::RenderFrameHost* rfh,
-                         const GURL& origin) {
+  void RequestPermissionFromCurrentDocument(PermissionType type,
+                                            content::RenderFrameHost* rfh) {
     base::RunLoop loop;
     quit_closure_ = loop.QuitClosure();
-    GetPermissionManager()->RequestPermission(
-        type, rfh, origin, true,
-        base::BindOnce(&PermissionManagerTest::OnPermissionChange,
-                       base::Unretained(this)));
+    GetPermissionManager()->RequestPermissionsFromCurrentDocument(
+        std::vector(1, type), rfh, true,
+        base::BindOnce(
+            [](base::OnceCallback<void(blink::mojom::PermissionStatus)>
+                   callback,
+               const std::vector<blink::mojom::PermissionStatus>& state) {
+              DCHECK_EQ(state.size(), 1U);
+              std::move(callback).Run(state[0]);
+            },
+            base::BindOnce(&PermissionManagerTest::OnPermissionChange,
+                           base::Unretained(this))));
     loop.Run();
   }
 
-  void RequestPermissionNonBlocking(PermissionType type,
-                                    content::RenderFrameHost* rfh,
-                                    const GURL& origin) {
-    GetPermissionManager()->RequestPermission(
-        type, rfh, origin, true,
-        base::BindOnce(&PermissionManagerTest::OnPermissionChange,
-                       base::Unretained(this)));
+  void RequestPermissionFromCurrentDocumentNonBlocking(
+      PermissionType type,
+      content::RenderFrameHost* rfh) {
+    GetPermissionManager()->RequestPermissionsFromCurrentDocument(
+        std::vector(1, type), rfh, true,
+        base::BindOnce(
+            [](base::OnceCallback<void(blink::mojom::PermissionStatus)>
+                   callback,
+               const std::vector<blink::mojom::PermissionStatus>& state) {
+              DCHECK_EQ(state.size(), 1U);
+              std::move(callback).Run(state[0]);
+            },
+            base::BindOnce(&PermissionManagerTest::OnPermissionChange,
+                           base::Unretained(this))));
   }
 
   PermissionStatus GetPermissionStatusForCurrentDocument(
@@ -657,7 +670,8 @@
 
   NavigateAndCommit(url());
 
-  RequestPermissionNonBlocking(PermissionType::GEOLOCATION, main_rfh(), url());
+  RequestPermissionFromCurrentDocumentNonBlocking(PermissionType::GEOLOCATION,
+                                                  main_rfh());
 
   EXPECT_FALSE(PendingRequestsEmpty());
 
@@ -764,7 +778,7 @@
   prompt_factory->set_response_type(PermissionRequestManager::ACCEPT_ALL);
   prompt_factory->DocumentOnLoadCompletedInPrimaryMainFrame();
 
-  RequestPermission(PermissionType::GEOLOCATION, child, GURL(kOrigin2));
+  RequestPermissionFromCurrentDocument(PermissionType::GEOLOCATION, child);
 
   EXPECT_TRUE(prompt_factory->RequestOriginSeen(GURL(kOrigin1)));
 
diff --git a/components/permissions/permission_util.cc b/components/permissions/permission_util.cc
index 0bc6cfd..82fb2361a 100644
--- a/components/permissions/permission_util.cc
+++ b/components/permissions/permission_util.cc
@@ -251,10 +251,10 @@
 
   content::WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(render_frame_host);
-  // If `allow_universal_access_from_file_urls` flag is enabled, a file can
-  // introduce discrepancy between GetLastCommittedURL and
-  // GetLastCommittedOrigin. In that case GetLastCommittedURL should be used
-  // for requesting and verifying permissions.
+  // If `allow_universal_access_from_file_urls` flag is enabled, a file:/// can
+  // change its url via history.pushState/replaceState to any other url,
+  // including about:blank. To avoid user confusion we should always use a
+  // visible url, in other words `GetLastCommittedURL`.
   if (web_contents->GetOrCreateWebPreferences()
           .allow_universal_access_from_file_urls &&
       render_frame_host->GetLastCommittedOrigin().GetURL().SchemeIsFile()) {
@@ -342,4 +342,20 @@
   return content_setting;
 }
 
+ContentSetting PermissionUtil::PermissionStatusToContentSetting(
+    blink::mojom::PermissionStatus status) {
+  switch (status) {
+    case blink::mojom::PermissionStatus::GRANTED:
+      return CONTENT_SETTING_ALLOW;
+    case blink::mojom::PermissionStatus::ASK:
+      return CONTENT_SETTING_ASK;
+    case blink::mojom::PermissionStatus::DENIED:
+    default:
+      return CONTENT_SETTING_BLOCK;
+  }
+
+  NOTREACHED();
+  return CONTENT_SETTING_DEFAULT;
+}
+
 }  // namespace permissions
diff --git a/components/permissions/permission_util.h b/components/permissions/permission_util.h
index 6f8f5b6..6054553 100644
--- a/components/permissions/permission_util.h
+++ b/components/permissions/permission_util.h
@@ -11,6 +11,7 @@
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/permissions/permission_request.h"
+#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
 
 namespace blink {
 enum class PermissionType;
@@ -86,6 +87,10 @@
   // Helper method to convert PermissionType to ContentSettingType.
   static ContentSettingsType PermissionTypeToContentSetting(
       blink::PermissionType permission);
+
+  // Helper method to convert PermissionStatus to ContentSetting.
+  static ContentSetting PermissionStatusToContentSetting(
+      blink::mojom::PermissionStatus status);
 };
 
 }  // namespace permissions
diff --git a/components/policy/core/common/mac_util.cc b/components/policy/core/common/mac_util.cc
index c94255a..2c6cf83 100644
--- a/components/policy/core/common/mac_util.cc
+++ b/components/policy/core/common/mac_util.cc
@@ -39,8 +39,10 @@
 void ArrayEntryToValue(const void* value, void* context) {
   std::unique_ptr<base::Value> converted =
       PropertyToValue(static_cast<CFPropertyListRef>(value));
-  if (converted)
-    static_cast<base::ListValue*>(context)->Append(std::move(converted));
+  if (converted) {
+    static_cast<base::ListValue*>(context)->GetList().Append(
+        base::Value::FromUniquePtrValue(std::move(converted)));
+  }
 }
 
 }  // namespace
diff --git a/components/policy/core/common/mac_util_unittest.cc b/components/policy/core/common/mac_util_unittest.cc
index b3e7826..dcfa118 100644
--- a/components/policy/core/common/mac_util_unittest.cc
+++ b/components/policy/core/common/mac_util_unittest.cc
@@ -41,9 +41,9 @@
   root.Set("emptyl", std::make_unique<base::Value>(base::Value::Type::LIST));
   base::ListValue list;
   for (base::DictionaryValue::Iterator it(root); !it.IsAtEnd(); it.Advance())
-    list.Append(std::make_unique<base::Value>(it.value().Clone()));
-  EXPECT_EQ(root.DictSize(), list.GetListDeprecated().size());
-  list.Append(std::make_unique<base::Value>(root.Clone()));
+    list.GetList().Append(it.value().Clone());
+  EXPECT_EQ(root.DictSize(), list.GetList().size());
+  list.GetList().Append(root.Clone());
   root.SetKey("list", list.Clone());
 
   // base::Value::Type::DICTIONARY
diff --git a/components/policy/core/common/policy_loader_win_unittest.cc b/components/policy/core/common/policy_loader_win_unittest.cc
index 9af7627..23a176e 100644
--- a/components/policy/core/common/policy_loader_win_unittest.cc
+++ b/components/policy/core/common/policy_loader_win_unittest.cc
@@ -587,8 +587,8 @@
   policy.SetIntKey("int", -123);
   policy.SetDoubleKey("double", 456.78e9);
   base::ListValue list;
-  list.Append(std::make_unique<base::Value>(policy.Clone()));
-  list.Append(std::make_unique<base::Value>(policy.Clone()));
+  list.GetList().Append(policy.Clone());
+  list.GetList().Append(policy.Clone());
   policy.SetKey("list", list.Clone());
   // Encode |policy| before adding the "dict" entry.
   std::string encoded_dict;
diff --git a/components/policy/core/common/registry_dict.cc b/components/policy/core/common/registry_dict.cc
index ff487c9..96cc77a 100644
--- a/components/policy/core/common/registry_dict.cc
+++ b/components/policy/core/common/registry_dict.cc
@@ -60,7 +60,7 @@
         absl::optional<base::Value> converted =
             ConvertRegistryValue(entry, schema.GetItems());
         if (converted.has_value())
-          result.Append(std::move(converted.value()));
+          result.GetList().Append(std::move(converted.value()));
       }
       return result;
     }
@@ -113,7 +113,7 @@
           absl::optional<base::Value> converted =
               ConvertRegistryValue(it.second, schema.GetItems());
           if (converted.has_value())
-            result.Append(std::move(converted.value()));
+            result.GetList().Append(std::move(converted.value()));
         }
         return result;
       }
@@ -338,7 +338,8 @@
         std::unique_ptr<base::Value> converted =
             entry->second->ConvertToJSON(item_schema);
         if (converted)
-          result->Append(std::move(converted));
+          result->GetList().Append(
+              base::Value::FromUniquePtrValue(std::move(converted)));
       }
       for (RegistryDict::ValueMap::const_iterator entry(values_.begin());
            entry != values_.end(); ++entry) {
@@ -347,7 +348,7 @@
         absl::optional<base::Value> converted =
             ConvertRegistryValue(entry->second, item_schema);
         if (converted.has_value())
-          result->Append(std::move(converted.value()));
+          result->GetList().Append(std::move(converted.value()));
       }
       return std::move(result);
     }
diff --git a/components/policy/core/common/registry_dict_unittest.cc b/components/policy/core/common/registry_dict_unittest.cc
index 78db177..4b2918ae 100644
--- a/components/policy/core/common/registry_dict_unittest.cc
+++ b/components/policy/core/common/registry_dict_unittest.cc
@@ -234,7 +234,7 @@
   expected_subdict->SetKey("two", string_value.Clone());
   expected.Set("three", std::move(expected_subdict));
   auto expected_list = std::make_unique<base::ListValue>();
-  expected_list->Append(std::make_unique<base::Value>(string_value.Clone()));
+  expected_list->GetList().Append(string_value.Clone());
   expected.Set("dict-to-list", std::move(expected_list));
   expected.SetBoolKey("int-to-bool", true);
   expected.SetDoubleKey("int-to-double", 42.0);
@@ -242,7 +242,7 @@
   expected.SetDoubleKey("string-to-double", 0.0);
   expected.SetIntKey("string-to-int", static_cast<int>(0));
   expected_list = std::make_unique<base::ListValue>();
-  expected_list->Append(std::make_unique<base::Value>("value"));
+  expected_list->GetList().Append("value");
   expected_subdict = std::make_unique<base::DictionaryValue>();
   expected_subdict->Set("key", std::move(expected_list));
   expected.Set("string-to-dict", std::move(expected_subdict));
@@ -278,9 +278,9 @@
 
   base::DictionaryValue expected;
   std::unique_ptr<base::ListValue> expected_list(new base::ListValue());
-  expected_list->Append(base::Value("1").Clone());
-  expected_list->Append(base::Value("2").Clone());
-  expected_list->Append(base::Value("4").Clone());
+  expected_list->GetList().Append(base::Value("1").Clone());
+  expected_list->GetList().Append(base::Value("2").Clone());
+  expected_list->GetList().Append(base::Value("4").Clone());
   expected.Set("dict-to-list", std::move(expected_list));
 
   EXPECT_EQ(expected, *actual);
@@ -345,7 +345,7 @@
   std::unique_ptr<base::DictionaryValue> expected_extension_settings(
       new base::DictionaryValue());
   std::unique_ptr<base::ListValue> list_value(new base::ListValue());
-  list_value->Append("*://*.google.com");
+  list_value->GetList().Append("*://*.google.com");
   std::unique_ptr<base::DictionaryValue> restrictions_properties(
       new base::DictionaryValue());
   restrictions_properties->Set(
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 4a32cfd..41142ce 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -29205,11 +29205,13 @@
           'name': 'PrimaryAccountKeepExistingData',
           'value': 'primary_account_keep_existing_data',
           'caption': 'A Managed account must be a primary account and the user can import existing data at the time of its creation',
+          'supported_on': ['chrome.*:102-'],
         },
         {
           'name': 'PrimaryAccountStrictKeepExistingData',
           'value': 'primary_account_strict_keep_existing_data',
           'caption': 'A Managed account must be a primary account and have no secondary accounts and the user can import existing data at the time of its creation',
+          'supported_on': ['chrome.*:102-'],
         },
       ],
       'default': 'none',
@@ -29219,10 +29221,10 @@
       'tags': [],
       'desc': '''
       If this policy is set to <ph name="POLICY_VALUE_PRIMARY_ACCOUNT">'primary_account'</ph>, after a signin into an a managed account subjected to this policy, the user be asked to create a new profile for the account.
-      If this policy is set to <ph name="POLICY_VALUE_PRIMARY_ACCOUNT_KEEP_EXISTING_DATA">'primary_account_keep_existing_data'</ph>, after a signin into an a managed account subjected to this policy, the user be asked to create a new profile for the account with an option to keep any existing browsing data.
+      If this policy is set to <ph name="POLICY_VALUE_PRIMARY_ACCOUNT_KEEP_EXISTING_DATA">'primary_account_keep_existing_data'</ph>, after a signin into an a managed account subjected to this policy, the user be asked to create a new profile for the account with an option to keep any existing browsing data. This option is supported on Chrome 102 and higher version.
 
       If this policy is set to <ph name="POLICY_VALUE_PRIMARY_ACCOUNT_STRICT">'primary_account_strict'</ph>, after a signin into an a managed account subjected to this policy, the user be asked to create a new profile for the account. This profile will not allow any secondary accounts.
-      If this policy is set to <ph name="POLICY_VALUE_PRIMARY_ACCOUNT_STRICT_KEEP_EXISTING_DATA">'primary_account_strict_keep_existing_data'</ph> after a signin into an a managed account subjected to this policy, the user be asked to create a new profile for the account with an option to keep any existing browsing data. This profile will not allow any secondary accounts.
+      If this policy is set to <ph name="POLICY_VALUE_PRIMARY_ACCOUNT_STRICT_KEEP_EXISTING_DATA">'primary_account_strict_keep_existing_data'</ph> after a signin into an a managed account subjected to this policy, the user be asked to create a new profile for the account with an option to keep any existing browsing data. This profile will not allow any secondary accounts. This option is supported on Chrome 102 and higher version.
 
       If this policy is set to <ph name="POLICY_VALUE_NONE">'none'</ph> or not set, managed accounts have no restrictions. This may result in a managed account being a secondary account, which disables its ability to receive policies set on the account by the admin.
 
diff --git a/components/search_engines/default_search_manager_unittest.cc b/components/search_engines/default_search_manager_unittest.cc
index efcc18a..1ba1c87 100644
--- a/components/search_engines/default_search_manager_unittest.cc
+++ b/components/search_engines/default_search_manager_unittest.cc
@@ -30,35 +30,35 @@
 // TODO(caitkp): TemplateURLData-ify this.
 void SetOverrides(sync_preferences::TestingPrefServiceSyncable* prefs,
                   bool update) {
-  prefs->SetUserPref(prefs::kSearchProviderOverridesVersion,
-                     std::make_unique<base::Value>(1));
-  auto overrides = std::make_unique<base::ListValue>();
-  auto entry = std::make_unique<base::Value>(base::Value::Type::DICTIONARY);
+  prefs->SetUserPref(prefs::kSearchProviderOverridesVersion, base::Value(1));
+  base::Value::List overrides;
+  base::Value::Dict entry;
 
-  entry->SetStringKey("name", update ? "new_foo" : "foo");
-  entry->SetStringKey("keyword", update ? "new_fook" : "fook");
-  entry->SetStringKey("search_url", "http://foo.com/s?q={searchTerms}");
-  entry->SetStringKey("favicon_url", "http://foi.com/favicon.ico");
-  entry->SetStringKey("encoding", "UTF-8");
-  entry->SetIntKey("id", 1001);
-  entry->SetStringKey("suggest_url", "http://foo.com/suggest?q={searchTerms}");
-  base::ListValue alternate_urls;
+  entry.Set("name", update ? "new_foo" : "foo");
+  entry.Set("keyword", update ? "new_fook" : "fook");
+  entry.Set("search_url", "http://foo.com/s?q={searchTerms}");
+  entry.Set("favicon_url", "http://foi.com/favicon.ico");
+  entry.Set("encoding", "UTF-8");
+  entry.Set("id", 1001);
+  entry.Set("suggest_url", "http://foo.com/suggest?q={searchTerms}");
+  base::Value::List alternate_urls;
   alternate_urls.Append("http://foo.com/alternate?q={searchTerms}");
-  entry->SetKey("alternate_urls", std::move(alternate_urls));
-  overrides->Append(std::move(entry));
+  entry.Set("alternate_urls", std::move(alternate_urls));
+  overrides.Append(std::move(entry));
 
-  entry = std::make_unique<base::Value>(base::Value::Type::DICTIONARY);
-  entry->SetIntKey("id", 1002);
-  entry->SetStringKey("name", update ? "new_bar" : "bar");
-  entry->SetStringKey("keyword", update ? "new_bark" : "bark");
-  entry->SetStringKey("encoding", std::string());
-  overrides->Append(std::make_unique<base::Value>(entry->Clone()));
-  entry->SetIntKey("id", 1003);
-  entry->SetStringKey("name", "baz");
-  entry->SetStringKey("keyword", "bazk");
-  entry->SetStringKey("encoding", "UTF-8");
-  overrides->Append(std::move(entry));
-  prefs->SetUserPref(prefs::kSearchProviderOverrides, std::move(overrides));
+  entry = base::Value::Dict();
+  entry.Set("id", 1002);
+  entry.Set("name", update ? "new_bar" : "bar");
+  entry.Set("keyword", update ? "new_bark" : "bark");
+  entry.Set("encoding", std::string());
+  overrides.Append(entry.Clone());
+  entry.Set("id", 1003);
+  entry.Set("name", "baz");
+  entry.Set("keyword", "bazk");
+  entry.Set("encoding", "UTF-8");
+  overrides.Append(std::move(entry));
+  prefs->SetUserPref(prefs::kSearchProviderOverrides,
+                     base::Value(std::move(overrides)));
 }
 
 void SetPolicy(sync_preferences::TestingPrefServiceSyncable* prefs,
diff --git a/components/segmentation_platform/internal/proto/model_metadata.proto b/components/segmentation_platform/internal/proto/model_metadata.proto
index 8644d54..a5136c6 100644
--- a/components/segmentation_platform/internal/proto/model_metadata.proto
+++ b/components/segmentation_platform/internal/proto/model_metadata.proto
@@ -15,10 +15,13 @@
 // new feature added to metadata proto, and add a log of the new changes in the
 // current version in this file.
 // Version 0 supports UMA features and aggregation in |features| field.
-// Version 1 supports UMA features and custom inputs in |input_features| field.
+// Version 1 supports UMA features, custom inputs and sql features in
+// |input_features| field.
 // Version 2 supports training data output collection in |training_outputs|
 // field.
-enum CurrentVersion { METADATA_VERSION = 0; }
+enum CurrentVersion {
+  METADATA_VERSION = 1;
+}
 
 // Version information for segmentation models.
 message VersionInfo {
diff --git a/components/services/screen_ai/proto/chrome_screen_ai.proto b/components/services/screen_ai/proto/chrome_screen_ai.proto
index 8962b4c..d04a8f6 100644
--- a/components/services/screen_ai/proto/chrome_screen_ai.proto
+++ b/components/services/screen_ai/proto/chrome_screen_ai.proto
@@ -10,6 +10,8 @@
 
 package chrome_screen_ai;
 
+// This option should be enabled for Chrome, but not in Google3.
+// TODO(https://crbug.com/1278249): Try to make this based on build commands.
 option optimize_for = LITE_RUNTIME;
 
 // A component of a given UI. This proto is filled based on
@@ -233,11 +235,14 @@
 
   // The predicted type of this component.
   message PredictedType {
-    Type type = 1;
+    oneof type_of {
+      Type enum_type = 1;
+      string string_type = 2;
+    }
 
     // A score in the range of [0, 1], indicating how confident the model is of
     // the given type prediction. Closer to 1 means more confident.
-    float score = 2;
+    float score = 3;
   }
 
   PredictedType predicted_type = 1;
diff --git a/components/services/screen_ai/proto/proto_convertor.cc b/components/services/screen_ai/proto/proto_convertor.cc
index 730bbf8..1f86cfb 100644
--- a/components/services/screen_ai/proto/proto_convertor.cc
+++ b/components/services/screen_ai/proto/proto_convertor.cc
@@ -44,17 +44,27 @@
 
     ui::AXNodeData node;
 
-    chrome_screen_ai::UIComponent::Type original_type =
-        uic.predicted_type().type();
     node.relative_bounds.bounds.set_x(uic.bounding_box().x());
     node.relative_bounds.bounds.set_y(uic.bounding_box().y());
     node.relative_bounds.bounds.set_width(uic.bounding_box().width());
     node.relative_bounds.bounds.set_height(uic.bounding_box().height());
 
-    // TODO(https://crbug.com/1278249): Add tests to ensure these two types
-    // match. Add a PRESUBMIT test that compares the proto and enum.
-    node.role = static_cast<ax::mojom::Role>(original_type);
-
+    switch (uic.predicted_type().type_of_case()) {
+      case chrome_screen_ai::UIComponent_PredictedType::kEnumType:
+        // TODO(https://crbug.com/1278249): Add tests to ensure these two types
+        // match. Add a PRESUBMIT test that compares the proto and enum.
+        node.role =
+            static_cast<ax::mojom::Role>(uic.predicted_type().enum_type());
+        break;
+      case chrome_screen_ai::UIComponent_PredictedType::kStringType:
+        node.role = ax::mojom::Role::kGenericContainer;
+        node.AddStringAttribute(ax::mojom::StringAttribute::kRoleDescription,
+                                uic.predicted_type().string_type());
+        break;
+      case chrome_screen_ai::UIComponent_PredictedType::TYPE_OF_NOT_SET:
+        NOTREACHED();
+        continue;
+    }
     updates.nodes.push_back(node);
   }
 
diff --git a/components/signin/core/browser/chrome_connected_header_helper.cc b/components/signin/core/browser/chrome_connected_header_helper.cc
index c79af94..15fa8016 100644
--- a/components/signin/core/browser/chrome_connected_header_helper.cc
+++ b/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -182,7 +182,7 @@
              google_util::IsYoutubeDomainUrl(
                  url, google_util::ALLOW_SUBDOMAIN,
                  google_util::DISALLOW_NON_STANDARD_PORTS) ||
-             gaia::IsGaiaSignonRealm(url.DeprecatedGetOriginAsURL());
+             gaia::HasGaiaSchemeHostPort(url);
     }
   }
 }
@@ -213,7 +213,7 @@
 
   if (!force_account_consistency && gaia_id.empty()) {
 #if BUILDFLAG(IS_ANDROID)
-    if (gaia::IsGaiaSignonRealm(url.DeprecatedGetOriginAsURL())) {
+    if (gaia::HasGaiaSchemeHostPort(url)) {
       parts.push_back(
           base::StringPrintf("%s=%s", kEligibleForConsistency, "true"));
       return base::JoinString(parts, is_header_request ? "," : ":");
diff --git a/components/signin/core/browser/dice_header_helper.cc b/components/signin/core/browser/dice_header_helper.cc
index aa1cacf4..0482585 100644
--- a/components/signin/core/browser/dice_header_helper.cc
+++ b/components/signin/core/browser/dice_header_helper.cc
@@ -204,7 +204,7 @@
   if (account_consistency_ != AccountConsistencyMethod::kDice)
     return false;
 
-  return gaia::IsGaiaSignonRealm(url.DeprecatedGetOriginAsURL());
+  return gaia::HasGaiaSchemeHostPort(url);
 }
 
 std::string DiceHeaderHelper::BuildRequestHeader(
diff --git a/components/signin/ios/browser/account_consistency_service.mm b/components/signin/ios/browser/account_consistency_service.mm
index 03de401f..9eb8f3a 100644
--- a/components/signin/ios/browser/account_consistency_service.mm
+++ b/components/signin/ios/browser/account_consistency_service.mm
@@ -52,7 +52,7 @@
 // Returns the registered, organization-identifying host, but no subdomains,
 // from the given GURL. Returns an empty string if the GURL is invalid.
 static std::string GetDomainFromUrl(const GURL& url) {
-  if (gaia::IsGaiaSignonRealm(url.DeprecatedGetOriginAsURL())) {
+  if (gaia::HasGaiaSchemeHostPort(url)) {
     return kGaiaDomain;
   }
   return net::registry_controlled_domains::GetDomainAndRegistry(
@@ -202,7 +202,7 @@
         {url, GURL(kGoogleUrl)});
   }
 
-  if (!gaia::IsGaiaSignonRealm(url.DeprecatedGetOriginAsURL())) {
+  if (!gaia::HasGaiaSchemeHostPort(url)) {
     std::move(callback).Run(PolicyDecision::Allow());
     return;
   }
@@ -309,7 +309,7 @@
   }
 
   if (delegate_ && show_consistency_web_signin_ &&
-      gaia::IsGaiaSignonRealm(url.DeprecatedGetOriginAsURL())) {
+      gaia::HasGaiaSchemeHostPort(url)) {
     delegate_->OnShowConsistencyPromo(url, web_state);
   }
   show_consistency_web_signin_ = false;
diff --git a/components/update_client/configurator.h b/components/update_client/configurator.h
index 657b9e3..cce961d 100644
--- a/components/update_client/configurator.h
+++ b/components/update_client/configurator.h
@@ -56,7 +56,8 @@
   virtual int UpdateDelay() const = 0;
 
   // The URLs for the update checks. The URLs are tried in order, the first one
-  // that succeeds wins.
+  // that succeeds wins. Since some components cannot be updated over HTTP,
+  // HTTPS URLs should appear first.
   virtual std::vector<GURL> UpdateUrl() const = 0;
 
   // The URLs for pings. Returns an empty vector if and only if pings are
diff --git a/components/update_client/test_configurator.cc b/components/update_client/test_configurator.cc
index dfddc4c..89ba034 100644
--- a/components/update_client/test_configurator.cc
+++ b/components/update_client/test_configurator.cc
@@ -75,8 +75,8 @@
 }
 
 std::vector<GURL> TestConfigurator::UpdateUrl() const {
-  if (!update_check_url_.is_empty())
-    return std::vector<GURL>(1, update_check_url_);
+  if (!update_check_urls_.empty())
+    return update_check_urls_;
 
   return MakeDefaultUrls();
 }
@@ -191,7 +191,11 @@
 }
 
 void TestConfigurator::SetUpdateCheckUrl(const GURL& url) {
-  update_check_url_ = url;
+  update_check_urls_ = {url};
+}
+
+void TestConfigurator::SetUpdateCheckUrls(const std::vector<GURL>& urls) {
+  update_check_urls_ = urls;
 }
 
 void TestConfigurator::SetPingUrl(const GURL& url) {
diff --git a/components/update_client/test_configurator.h b/components/update_client/test_configurator.h
index d19fa702..9d49d90 100644
--- a/components/update_client/test_configurator.h
+++ b/components/update_client/test_configurator.h
@@ -109,6 +109,7 @@
   void SetDownloadPreference(const std::string& download_preference);
   void SetEnabledCupSigning(bool use_cup_signing);
   void SetUpdateCheckUrl(const GURL& url);
+  void SetUpdateCheckUrls(const std::vector<GURL>& urls);
   void SetPingUrl(const GURL& url);
   void SetCrxDownloaderFactory(
       scoped_refptr<CrxDownloaderFactory> crx_downloader_factory);
@@ -130,7 +131,7 @@
   std::string download_preference_;
   bool enabled_cup_signing_;
   raw_ptr<PrefService> pref_service_;  // Not owned by this class.
-  GURL update_check_url_;
+  std::vector<GURL> update_check_urls_;
   GURL ping_url_;
 
   scoped_refptr<update_client::UnzipChromiumFactory> unzip_factory_;
diff --git a/components/update_client/update_checker.cc b/components/update_client/update_checker.cc
index 1647f5c..8b7c644 100644
--- a/components/update_client/update_checker.cc
+++ b/components/update_client/update_checker.cc
@@ -32,24 +32,15 @@
 #include "components/update_client/request_sender.h"
 #include "components/update_client/task_traits.h"
 #include "components/update_client/update_client.h"
+#include "components/update_client/update_engine.h"
 #include "components/update_client/utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
 namespace update_client {
 
 namespace {
 
-// Returns true if at least one item requires network encryption.
-bool IsEncryptionRequired(const IdToComponentPtrMap& components) {
-  for (const auto& item : components) {
-    const auto& component = item.second;
-    if (component->crx_component() &&
-        component->crx_component()->requires_network_encryption)
-      return true;
-  }
-  return false;
-}
-
 class UpdateCheckerImpl : public UpdateChecker {
  public:
   UpdateCheckerImpl(scoped_refptr<Configurator> config,
@@ -62,24 +53,25 @@
 
   // Overrides for UpdateChecker.
   void CheckForUpdates(
-      const std::string& session_id,
-      const std::vector<std::string>& ids_checked,
-      const IdToComponentPtrMap& components,
+      scoped_refptr<UpdateContext> context,
       const base::flat_map<std::string, std::string>& additional_attributes,
       UpdateCheckCallback update_check_callback) override;
 
  private:
   UpdaterStateAttributes ReadUpdaterStateAttributes() const;
   void CheckForUpdatesHelper(
-      const std::string& session_id,
-      const IdToComponentPtrMap& components,
+      scoped_refptr<UpdateContext> context,
+      const std::vector<GURL>& urls,
       const base::flat_map<std::string, std::string>& additional_attributes,
       const UpdaterStateAttributes& updater_state_attributes,
       const std::set<std::string>& active_ids);
-  void OnRequestSenderComplete(int error,
+  void OnRequestSenderComplete(scoped_refptr<UpdateContext> context,
+                               absl::optional<base::OnceClosure> fallback,
+                               int error,
                                const std::string& response,
                                int retry_after_sec);
-  void UpdateCheckSucceeded(const ProtocolParser::Results& results,
+  void UpdateCheckSucceeded(scoped_refptr<UpdateContext> context,
+                            const ProtocolParser::Results& results,
                             int retry_after_sec);
   void UpdateCheckFailed(ErrorCategory error_category,
                          int error,
@@ -89,7 +81,6 @@
 
   const scoped_refptr<Configurator> config_;
   raw_ptr<PersistedData> metadata_ = nullptr;
-  std::vector<std::string> ids_checked_;
   UpdateCheckCallback update_check_callback_;
   std::unique_ptr<RequestSender> request_sender_;
 };
@@ -103,19 +94,16 @@
 }
 
 void UpdateCheckerImpl::CheckForUpdates(
-    const std::string& session_id,
-    const std::vector<std::string>& ids_checked,
-    const IdToComponentPtrMap& components,
+    scoped_refptr<UpdateContext> context,
     const base::flat_map<std::string, std::string>& additional_attributes,
     UpdateCheckCallback update_check_callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  ids_checked_ = ids_checked;
   update_check_callback_ = std::move(update_check_callback);
 
   auto check_for_updates_invoker = base::BindOnce(
       &UpdateCheckerImpl::CheckForUpdatesHelper, base::Unretained(this),
-      session_id, std::cref(components), additional_attributes);
+      context, config_->UpdateUrl(), additional_attributes);
 
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, kTaskTraits,
@@ -132,7 +120,7 @@
                                     updater_state_attributes));
           },
           std::move(check_for_updates_invoker), base::Unretained(metadata_),
-          ids_checked));
+          context->components_to_check_for_updates));
 }
 
 // This function runs on the blocking pool task runner.
@@ -148,36 +136,49 @@
 }
 
 void UpdateCheckerImpl::CheckForUpdatesHelper(
-    const std::string& session_id,
-    const IdToComponentPtrMap& components,
+    scoped_refptr<UpdateContext> context,
+    const std::vector<GURL>& urls,
     const base::flat_map<std::string, std::string>& additional_attributes,
     const UpdaterStateAttributes& updater_state_attributes,
     const std::set<std::string>& active_ids) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  auto urls(config_->UpdateUrl());
-  if (IsEncryptionRequired(components))
-    RemoveUnsecureUrls(&urls);
+  if (urls.empty()) {
+    UpdateCheckFailed(ErrorCategory::kUpdateCheck,
+                      static_cast<int>(ProtocolError::MISSING_URLS), 0);
+    return;
+  }
+  GURL url = urls.front();
 
   // Components in this update check are either all foreground, or all
   // background since this member is inherited from the component's update
   // context. Pick the state of the first component to use in the update check.
-  DCHECK(!components.empty());
-  const bool is_foreground = components.at(ids_checked_[0])->is_foreground();
+  DCHECK(!context->components.empty());
+  const bool is_foreground =
+      context->components.cbegin()->second->is_foreground();
   DCHECK(
-      std::all_of(components.cbegin(), components.cend(),
+      std::all_of(context->components.cbegin(), context->components.cend(),
                   [is_foreground](IdToComponentPtrMap::const_reference& elem) {
                     return is_foreground == elem.second->is_foreground();
                   }));
 
+  std::vector<std::string> sent_ids;
+
   std::vector<protocol_request::App> apps;
-  for (const auto& app_id : ids_checked_) {
-    DCHECK_EQ(1u, components.count(app_id));
-    const auto& component = components.at(app_id);
+  for (const auto& app_id : context->components_to_check_for_updates) {
+    DCHECK_EQ(1u, context->components.count(app_id));
+    const auto& component = context->components.at(app_id);
     DCHECK_EQ(component->id(), app_id);
     const auto& crx_component = component->crx_component();
     DCHECK(crx_component);
 
+    if (crx_component->requires_network_encryption &&
+        !url.SchemeIsCryptographic()) {
+      continue;
+    }
+
+    sent_ids.push_back(app_id);
+
     std::string install_source;
     if (!crx_component->install_source.empty())
       install_source = crx_component->install_source;
@@ -207,8 +208,15 @@
         absl::nullopt));
   }
 
+  if (sent_ids.empty()) {
+    // No apps could be checked over this URL.
+    UpdateCheckFailed(ErrorCategory::kUpdateCheck,
+                      static_cast<int>(ProtocolError::MISSING_URLS), 0);
+    return;
+  }
+
   const auto request = MakeProtocolRequest(
-      !config_->IsPerUserInstall(), session_id, config_->GetProdId(),
+      !config_->IsPerUserInstall(), context->session_id, config_->GetProdId(),
       config_->GetBrowserVersion().GetString(), config_->GetChannel(),
       config_->GetOSLongName(), config_->GetDownloadPreference(),
       config_->IsMachineExternallyManaged(), additional_attributes,
@@ -216,18 +224,28 @@
 
   request_sender_ = std::make_unique<RequestSender>(config_);
   request_sender_->Send(
-      urls,
+      {url},
       BuildUpdateCheckExtraRequestHeaders(config_->GetProdId(),
                                           config_->GetBrowserVersion(),
-                                          ids_checked_, is_foreground),
+                                          sent_ids, is_foreground),
       config_->GetProtocolHandlerFactory()->CreateSerializer()->Serialize(
           request),
       config_->EnabledCupSigning(),
       base::BindOnce(&UpdateCheckerImpl::OnRequestSenderComplete,
-                     base::Unretained(this)));
+                     base::Unretained(this), context,
+                     urls.size() > 1
+                         ? absl::optional<base::OnceClosure>(base::BindOnce(
+                               &UpdateCheckerImpl::CheckForUpdatesHelper,
+                               base::Unretained(this), context,
+                               std::vector<GURL>(urls.begin() + 1, urls.end()),
+                               additional_attributes, updater_state_attributes,
+                               active_ids))
+                         : absl::nullopt));
 }
 
 void UpdateCheckerImpl::OnRequestSenderComplete(
+    scoped_refptr<UpdateContext> context,
+    absl::optional<base::OnceClosure> fallback,
     int error,
     const std::string& response,
     int retry_after_sec) {
@@ -235,7 +253,11 @@
 
   if (error) {
     VLOG(1) << "RequestSender failed " << error;
-    UpdateCheckFailed(ErrorCategory::kUpdateCheck, error, retry_after_sec);
+    if (fallback && retry_after_sec <= 0) {
+      std::move(*fallback).Run();
+    } else {
+      UpdateCheckFailed(ErrorCategory::kUpdateCheck, error, retry_after_sec);
+    }
     return;
   }
 
@@ -249,10 +271,11 @@
   }
 
   DCHECK_EQ(0, error);
-  UpdateCheckSucceeded(parser->results(), retry_after_sec);
+  UpdateCheckSucceeded(context, parser->results(), retry_after_sec);
 }
 
 void UpdateCheckerImpl::UpdateCheckSucceeded(
+    scoped_refptr<UpdateContext> context,
     const ProtocolParser::Results& results,
     int retry_after_sec) {
   DCHECK(thread_checker_.CalledOnValidThread());
@@ -276,7 +299,8 @@
                      ErrorCategory::kNone, 0, retry_after_sec);
 
   if (daynum != ProtocolParser::kNoDaystart) {
-    metadata_->SetDateLastData(ids_checked_, daynum, std::move(reply));
+    metadata_->SetDateLastData(context->components_to_check_for_updates, daynum,
+                               std::move(reply));
     return;
   }
 
diff --git a/components/update_client/update_checker.h b/components/update_client/update_checker.h
index 29df873..f0cf9a6 100644
--- a/components/update_client/update_checker.h
+++ b/components/update_client/update_checker.h
@@ -21,6 +21,7 @@
 
 class Configurator;
 class PersistedData;
+struct UpdateContext;
 
 class UpdateChecker {
  public:
@@ -40,15 +41,11 @@
   virtual ~UpdateChecker() = default;
 
   // Initiates an update check for the components specified by their ids.
-  // |additional_attributes| provides a way to customize the <request> element.
-  // |is_foreground| controls the value of "X-Goog-Update-Interactivity"
-  // header which is sent with the update check.
-  // On completion, the state of |components| is mutated as required by the
-  // server response received.
+  // `update_context` contains the updateable apps. `additional_attributes`
+  // specifies any extra request data to send. On completion, the state of
+  // `components` is mutated as required by the server response received.
   virtual void CheckForUpdates(
-      const std::string& session_id,
-      const std::vector<std::string>& ids_to_check,
-      const IdToComponentPtrMap& components,
+      scoped_refptr<UpdateContext> update_context,
       const base::flat_map<std::string, std::string>& additional_attributes,
       UpdateCheckCallback update_check_callback) = 0;
 
diff --git a/components/update_client/update_checker_unittest.cc b/components/update_client/update_checker_unittest.cc
index f2555a2..ed69b7a 100644
--- a/components/update_client/update_checker_unittest.cc
+++ b/components/update_client/update_checker_unittest.cc
@@ -140,6 +140,7 @@
   retry_after_sec_ = 0;
   update_context_ = MakeMockUpdateContext();
   update_context_->is_foreground = is_foreground_;
+  update_context_->components_to_check_for_updates = {kUpdateItemId};
 }
 
 void UpdateCheckerTest::TearDown() {
@@ -230,16 +231,14 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] =
+  update_context_->components[kUpdateItemId] =
       MakeComponent("TEST", "foobar_install_data_index");
 
-  auto& component = components[kUpdateItemId];
+  auto& component = update_context_->components[kUpdateItemId];
   component->crx_component_->installer_attributes["ap"] = "some_ap";
 
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components,
-      {{"extra", "params"}, {"testrequest", "1"}},
+      update_context_, {{"extra", "params"}, {"testrequest", "1"}},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -353,15 +352,14 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent("TEST");
+  update_context_->components[kUpdateItemId] = MakeComponent("TEST");
 
   // Make "ap" too long.
-  auto& component = components[kUpdateItemId];
+  auto& component = update_context_->components[kUpdateItemId];
   component->crx_component_->installer_attributes["ap"] = std::string(257, 'a');
 
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components, {},
+      update_context_, {},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
 
@@ -396,11 +394,10 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent("TOOLONG");
+  update_context_->components[kUpdateItemId] = MakeComponent("TOOLONG");
 
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components, {},
+      update_context_, {},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
 
@@ -427,6 +424,34 @@
                          ->GetString());
 }
 
+TEST_P(UpdateCheckerTest, UpdateCheckFallback) {
+  config_->SetUpdateCheckUrls(
+      {GURL("https://localhost2/update2"), GURL("https://localhost2/update2")});
+
+  // 404 first.
+  EXPECT_TRUE(post_interceptor_->ExpectRequest(
+      std::make_unique<PartialMatch>("updatecheck"), net::HTTP_NOT_FOUND));
+  // Then OK.
+  EXPECT_TRUE(post_interceptor_->ExpectRequest(
+      std::make_unique<PartialMatch>("updatecheck"),
+      test_file("updatecheck_reply_1.json")));
+
+  update_checker_ = UpdateChecker::Create(config_, metadata_.get());
+
+  update_context_->components[kUpdateItemId] = MakeComponent("TOOLONG");
+
+  update_checker_->CheckForUpdates(
+      update_context_, {},
+      base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
+                     base::Unretained(this)));
+
+  RunThreads();
+  EXPECT_EQ(2, post_interceptor_->GetHitCount())
+      << post_interceptor_->GetRequestsAsString();
+  EXPECT_EQ(2, post_interceptor_->GetCount())
+      << post_interceptor_->GetRequestsAsString();
+}
+
 // Simulates a 403 server response error.
 TEST_P(UpdateCheckerTest, UpdateCheckError) {
   EXPECT_TRUE(post_interceptor_->ExpectRequest(
@@ -434,11 +459,10 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components, {},
+      update_context_, {},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -462,12 +486,10 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components,
-      {{"extra", "params"}},
+      update_context_, {{"extra", "params"}},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -491,11 +513,10 @@
   config_->SetEnabledCupSigning(true);
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent("TEST");
+  update_context_->components[kUpdateItemId] = MakeComponent("TEST");
 
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components, {},
+      update_context_, {},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
 
@@ -539,14 +560,13 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
-  auto& component = components[kUpdateItemId];
+  auto& component = update_context_->components[kUpdateItemId];
   component->crx_component_->requires_network_encryption = true;
 
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components, {},
+      update_context_, {},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -567,22 +587,19 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
   // Do two update-checks.
   activity_data_service_->SetDaysSinceLastRollCall(kUpdateItemId, 5);
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components,
-      {{"extra", "params"}},
+      update_context_, {{"extra", "params"}},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components,
-      {{"extra", "params"}},
+      update_context_, {{"extra", "params"}},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -618,14 +635,12 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
   activity_data_service_->SetActiveBit(kUpdateItemId, true);
   activity_data_service_->SetDaysSinceLastActive(kUpdateItemId, 10);
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components,
-      {{"extra", "params"}},
+      update_context_, {{"extra", "params"}},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -636,8 +651,7 @@
   activity_data_service_->SetActiveBit(kUpdateItemId, true);
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components,
-      {{"extra", "params"}},
+      update_context_, {{"extra", "params"}},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -647,8 +661,7 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components,
-      {{"extra", "params"}},
+      update_context_, {{"extra", "params"}},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -693,10 +706,9 @@
 TEST_P(UpdateCheckerTest, UpdateCheckInstallSource) {
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
-  auto& component = components[kUpdateItemId];
+  auto& component = update_context_->components[kUpdateItemId];
   auto crx_component = component->crx_component();
 
   if (is_foreground_) {
@@ -707,7 +719,7 @@
           std::make_unique<PartialMatch>("updatecheck"),
           test_file("updatecheck_reply_1.json")));
       update_checker_->CheckForUpdates(
-          update_context_->session_id, {kUpdateItemId}, components, {},
+          update_context_, {},
           base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                          base::Unretained(this)));
       RunThreads();
@@ -729,7 +741,7 @@
       crx_component->install_location = "policy";
       component->set_crx_component(*crx_component);
       update_checker_->CheckForUpdates(
-          update_context_->session_id, {kUpdateItemId}, components, {},
+          update_context_, {},
           base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                          base::Unretained(this)));
       RunThreads();
@@ -752,7 +764,7 @@
         std::make_unique<PartialMatch>("updatecheck"),
         test_file("updatecheck_reply_1.json")));
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -773,7 +785,7 @@
     crx_component->install_location = "external";
     component->set_crx_component(*crx_component);
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -790,10 +802,9 @@
 TEST_P(UpdateCheckerTest, ComponentDisabled) {
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
-  auto& component = components[kUpdateItemId];
+  auto& component = update_context_->components[kUpdateItemId];
   auto crx_component = component->crx_component();
 
   {
@@ -803,7 +814,7 @@
         std::make_unique<PartialMatch>("updatecheck"),
         test_file("updatecheck_reply_1.json")));
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -825,7 +836,7 @@
         std::make_unique<PartialMatch>("updatecheck"),
         test_file("updatecheck_reply_1.json")));
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -847,7 +858,7 @@
         std::make_unique<PartialMatch>("updatecheck"),
         test_file("updatecheck_reply_1.json")));
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -870,7 +881,7 @@
         std::make_unique<PartialMatch>("updatecheck"),
         test_file("updatecheck_reply_1.json")));
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -894,7 +905,7 @@
         std::make_unique<PartialMatch>("updatecheck"),
         test_file("updatecheck_reply_1.json")));
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -920,7 +931,7 @@
         std::make_unique<PartialMatch>("updatecheck"),
         test_file("updatecheck_reply_1.json")));
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -942,10 +953,9 @@
 TEST_P(UpdateCheckerTest, UpdateCheckUpdateDisabled) {
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
-  auto& component = components[kUpdateItemId];
+  auto& component = update_context_->components[kUpdateItemId];
   auto crx_component = component->crx_component();
 
   // Ignore this test parameter to keep the test simple.
@@ -961,7 +971,7 @@
         std::make_unique<PartialMatch>("updatecheck"),
         test_file("updatecheck_reply_1.json")));
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -987,7 +997,7 @@
         std::make_unique<PartialMatch>("updatecheck"),
         test_file("updatecheck_reply_1.json")));
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -1006,10 +1016,9 @@
 TEST_P(UpdateCheckerTest, SameVersionUpdateAllowed) {
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
-  auto& component = components[kUpdateItemId];
+  auto& component = update_context_->components[kUpdateItemId];
   auto crx_component = component->crx_component();
   EXPECT_FALSE(crx_component->same_version_update_allowed);
   {
@@ -1021,7 +1030,7 @@
         std::make_unique<PartialMatch>("updatecheck"),
         test_file("updatecheck_reply_noupdate.json")));
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -1044,7 +1053,7 @@
         std::make_unique<PartialMatch>("updatecheck"),
         test_file("updatecheck_reply_noupdate.json")));
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
@@ -1063,11 +1072,10 @@
       test_file("updatecheck_reply_noupdate.json")));
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components, {},
+      update_context_, {},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -1101,14 +1109,13 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent("TEST");
+  update_context_->components[kUpdateItemId] = MakeComponent("TEST");
 
   // Ignore this test parameter to keep the test simple.
   update_context_->is_foreground = false;
 
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components, {},
+      update_context_, {},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -1145,12 +1152,11 @@
       std::move(quit_closure)));
   post_interceptor_->Pause();
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components, {},
+      update_context_, {},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   runloop.Run();
@@ -1165,11 +1171,10 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components, {},
+      update_context_, {},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -1194,11 +1199,10 @@
 
   update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-  IdToComponentPtrMap components;
-  components[kUpdateItemId] = MakeComponent();
+  update_context_->components[kUpdateItemId] = MakeComponent();
 
   update_checker_->CheckForUpdates(
-      update_context_->session_id, {kUpdateItemId}, components, {},
+      update_context_, {},
       base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                      base::Unretained(this)));
   RunThreads();
@@ -1224,12 +1228,11 @@
         test_file("updatecheck_reply_noupdate.json")));
     update_checker_ = UpdateChecker::Create(config_, metadata_.get());
 
-    IdToComponentPtrMap components;
-    components[kUpdateItemId] = MakeComponent();
+    update_context_->components[kUpdateItemId] = MakeComponent();
 
     config_->SetIsMachineExternallyManaged(is_managed);
     update_checker_->CheckForUpdates(
-        update_context_->session_id, {kUpdateItemId}, components, {},
+        update_context_, {},
         base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
                        base::Unretained(this)));
     RunThreads();
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc
index edcd0e6..e6fc6da 100644
--- a/components/update_client/update_client_unittest.cc
+++ b/components/update_client/update_client_unittest.cc
@@ -38,6 +38,7 @@
 #include "components/update_client/update_checker.h"
 #include "components/update_client/update_client_errors.h"
 #include "components/update_client/update_client_internal.h"
+#include "components/update_client/update_engine.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -301,18 +302,16 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(1u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(1u, context->components_to_check_for_updates.size());
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-      EXPECT_EQ(id, ids_to_check.front());
-      EXPECT_EQ(1u, components.count(id));
+      EXPECT_EQ(id, context->components_to_check_for_updates.front());
+      EXPECT_EQ(1u, context->components.count(id));
 
-      auto& component = components.at(id);
+      auto& component = context->components.at(id);
 
       EXPECT_TRUE(component->is_foreground());
 
@@ -430,9 +429,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       /*
@@ -459,14 +456,14 @@
         </app>
       </response>
       */
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(2u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(2u, context->components_to_check_for_updates.size());
 
       ProtocolParser::Results results;
       {
         const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-        EXPECT_EQ(id, ids_to_check[0]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result::Manifest::Package package;
         package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
@@ -482,20 +479,20 @@
         result.manifest.packages.push_back(package);
         results.list.push_back(result);
 
-        EXPECT_FALSE(components.at(id)->is_foreground());
+        EXPECT_FALSE(context->components.at(id)->is_foreground());
       }
 
       {
         const std::string id = "abagagagagagagagagagagagagagagag";
-        EXPECT_EQ(id, ids_to_check[1]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[1]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result result;
         result.extension_id = id;
         result.status = "noupdate";
         results.list.push_back(result);
 
-        EXPECT_FALSE(components.at(id)->is_foreground());
+        EXPECT_FALSE(context->components.at(id)->is_foreground());
       }
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -684,9 +681,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       /*
@@ -710,14 +705,14 @@
         </app>
       </response>
       */
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(2u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(2u, context->components_to_check_for_updates.size());
 
       ProtocolParser::Results results;
       {
         const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-        EXPECT_EQ(id, ids_to_check[0]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result::Manifest::Package package;
         package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
@@ -733,7 +728,7 @@
         result.manifest.packages.push_back(package);
         results.list.push_back(result);
 
-        EXPECT_FALSE(components.at(id)->is_foreground());
+        EXPECT_FALSE(context->components.at(id)->is_foreground());
       }
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -912,9 +907,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       /*
@@ -938,14 +931,14 @@
         </app>
       </response>
       */
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(1u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(1u, context->components_to_check_for_updates.size());
 
       ProtocolParser::Results results;
       {
         const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-        EXPECT_EQ(id, ids_to_check[0]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result::Manifest::Package package;
         package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
@@ -961,7 +954,7 @@
         result.manifest.packages.push_back(package);
         results.list.push_back(result);
 
-        EXPECT_FALSE(components.at(id)->is_foreground());
+        EXPECT_FALSE(context->components.at(id)->is_foreground());
       }
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -1119,9 +1112,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       NOTREACHED();
@@ -1233,9 +1224,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       /*
@@ -1274,14 +1263,14 @@
       </response>
       */
 
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(2u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(2u, context->components_to_check_for_updates.size());
 
       ProtocolParser::Results results;
       {
         const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-        EXPECT_EQ(id, ids_to_check[0]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result::Manifest::Package package;
         package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
@@ -1300,8 +1289,8 @@
 
       {
         const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
-        EXPECT_EQ(id, ids_to_check[1]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[1]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result::Manifest::Package package;
         package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
@@ -1535,12 +1524,10 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
-      EXPECT_FALSE(session_id.empty());
+      EXPECT_FALSE(context->session_id.empty());
 
       static int num_call = 0;
       ++num_call;
@@ -1569,8 +1556,8 @@
         </response>
         */
         const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
-        EXPECT_EQ(id, ids_to_check[0]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result::Manifest::Package package;
         package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
@@ -1612,8 +1599,8 @@
         </response>
         */
         const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
-        EXPECT_EQ(id, ids_to_check[0]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result::Manifest::Package package;
         package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx";
@@ -1943,9 +1930,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       /*
@@ -1969,11 +1954,11 @@
         </app>
       </response>
       */
-      EXPECT_FALSE(session_id.empty());
+      EXPECT_FALSE(context->session_id.empty());
 
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-      EXPECT_EQ(id, ids_to_check[0]);
-      EXPECT_EQ(1u, components.count(id));
+      EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+      EXPECT_EQ(1u, context->components.count(id));
 
       ProtocolParser::Result::Manifest::Package package;
       package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
@@ -2151,12 +2136,10 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
-      EXPECT_FALSE(session_id.empty());
+      EXPECT_FALSE(context->session_id.empty());
 
       static int num_call = 0;
       ++num_call;
@@ -2186,8 +2169,8 @@
         </response>
         */
         const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
-        EXPECT_EQ(id, ids_to_check[0]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result::Manifest::Package package;
         package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
@@ -2230,8 +2213,8 @@
         </response>
         */
         const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
-        EXPECT_EQ(id, ids_to_check[0]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result::Manifest::Package package;
         package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx";
@@ -2497,18 +2480,16 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(1u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(1u, context->components_to_check_for_updates.size());
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-      EXPECT_EQ(id, ids_to_check.front());
-      EXPECT_EQ(1u, components.count(id));
+      EXPECT_EQ(id, context->components_to_check_for_updates.front());
+      EXPECT_EQ(1u, context->components.count(id));
 
-      auto& component = components.at(id);
+      auto& component = context->components.at(id);
 
       EXPECT_FALSE(component->is_foreground());
 
@@ -2640,9 +2621,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       /*
@@ -2667,12 +2646,12 @@
         </app>
       </response>
       */
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(1u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(1u, context->components_to_check_for_updates.size());
 
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-      EXPECT_EQ(id, ids_to_check[0]);
-      EXPECT_EQ(1u, components.count(id));
+      EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+      EXPECT_EQ(1u, context->components.count(id));
 
       ProtocolParser::Result::Manifest::Package package;
       package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
@@ -2694,7 +2673,7 @@
       results.list.push_back(result);
 
       // Verify that calling Install sets ondemand.
-      EXPECT_TRUE(components.at(id)->is_foreground());
+      EXPECT_TRUE(context->components.at(id)->is_foreground());
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
@@ -2873,9 +2852,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       NOTREACHED();
@@ -2995,16 +2972,14 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(1u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(1u, context->components_to_check_for_updates.size());
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-      EXPECT_EQ(id, ids_to_check.front());
-      EXPECT_EQ(1u, components.count(id));
+      EXPECT_EQ(id, context->components_to_check_for_updates.front());
+      EXPECT_EQ(1u, context->components.count(id));
 
       ProtocolParser::Result result;
       result.extension_id = id;
@@ -3014,7 +2989,7 @@
       results.list.push_back(result);
 
       // Verify that calling Install sets |is_foreground| for the component.
-      EXPECT_TRUE(components.at(id)->is_foreground());
+      EXPECT_TRUE(context->components.at(id)->is_foreground());
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
@@ -3119,9 +3094,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       NOTREACHED();
@@ -3177,9 +3150,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       NOTREACHED();
@@ -3286,12 +3257,10 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
-      EXPECT_FALSE(session_id.empty());
+      EXPECT_FALSE(context->session_id.empty());
 
       static int num_call = 0;
       ++num_call;
@@ -3304,10 +3273,10 @@
         retry_after_sec = 60 * 60;  // 1 hour.
       }
 
-      EXPECT_EQ(1u, ids_to_check.size());
+      EXPECT_EQ(1u, context->components_to_check_for_updates.size());
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-      EXPECT_EQ(id, ids_to_check.front());
-      EXPECT_EQ(1u, components.count(id));
+      EXPECT_EQ(id, context->components_to_check_for_updates.front());
+      EXPECT_EQ(1u, context->components.count(id));
 
       ProtocolParser::Result result;
       result.extension_id = id;
@@ -3465,9 +3434,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       /*
@@ -3506,14 +3473,14 @@
       </response>
       */
 
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(2u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(2u, context->components_to_check_for_updates.size());
 
       ProtocolParser::Results results;
       {
         const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-        EXPECT_EQ(id, ids_to_check[0]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result::Manifest::Package package;
         package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx";
@@ -3532,8 +3499,8 @@
 
       {
         const std::string id = "ihfokbkgjpifnbbojhneepfflplebdkc";
-        EXPECT_EQ(id, ids_to_check[1]);
-        EXPECT_EQ(1u, components.count(id));
+        EXPECT_EQ(id, context->components_to_check_for_updates[1]);
+        EXPECT_EQ(1u, context->components.count(id));
 
         ProtocolParser::Result::Manifest::Package package;
         package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx";
@@ -3729,16 +3696,14 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(1u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(1u, context->components_to_check_for_updates.size());
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-      EXPECT_EQ(id, ids_to_check.front());
-      EXPECT_EQ(1u, components.count(id));
+      EXPECT_EQ(id, context->components_to_check_for_updates.front());
+      EXPECT_EQ(1u, context->components.count(id));
       base::ThreadTaskRunnerHandle::Get()->PostTask(
           FROM_HERE,
           base::BindOnce(std::move(update_check_callback), absl::nullopt,
@@ -3878,13 +3843,11 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(4u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(4u, context->components_to_check_for_updates.size());
 
       const std::string update_response =
           ")]}'"
@@ -4031,9 +3994,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       /*
@@ -4059,12 +4020,12 @@
         </app>
       </response>
       */
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(1u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(1u, context->components_to_check_for_updates.size());
 
       const std::string id = "gjpmebpgbhcamgdgjcmnjfhggjpgcimm";
-      EXPECT_EQ(id, ids_to_check[0]);
-      EXPECT_EQ(1u, components.count(id));
+      EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+      EXPECT_EQ(1u, context->components.count(id));
 
       ProtocolParser::Result::Manifest::Package package;
       package.name = "runaction_test_win.crx3";
@@ -4220,9 +4181,7 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
       /*
@@ -4239,11 +4198,11 @@
         </app>
       </response>
       */
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(1u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(1u, context->components_to_check_for_updates.size());
       const std::string id = "gjpmebpgbhcamgdgjcmnjfhggjpgcimm";
-      EXPECT_EQ(id, ids_to_check[0]);
-      EXPECT_EQ(1u, components.count(id));
+      EXPECT_EQ(id, context->components_to_check_for_updates[0]);
+      EXPECT_EQ(1u, context->components.count(id));
 
       ProtocolParser::Result result;
       result.extension_id = id;
@@ -4402,18 +4361,16 @@
     }
 
     void CheckForUpdates(
-        const std::string& session_id,
-        const std::vector<std::string>& ids_to_check,
-        const IdToComponentPtrMap& components,
+        scoped_refptr<UpdateContext> context,
         const base::flat_map<std::string, std::string>& additional_attributes,
         UpdateCheckCallback update_check_callback) override {
-      EXPECT_FALSE(session_id.empty());
-      EXPECT_EQ(1u, ids_to_check.size());
+      EXPECT_FALSE(context->session_id.empty());
+      EXPECT_EQ(1u, context->components_to_check_for_updates.size());
       const std::string id = "jebgalgnebhfojomionfpkfelancnnkf";
-      EXPECT_EQ(id, ids_to_check.front());
-      EXPECT_EQ(1u, components.count(id));
+      EXPECT_EQ(id, context->components_to_check_for_updates.front());
+      EXPECT_EQ(1u, context->components.count(id));
 
-      auto& component = components.at(id);
+      auto& component = context->components.at(id);
 
       EXPECT_TRUE(component->is_foreground());
 
diff --git a/components/update_client/update_engine.cc b/components/update_client/update_engine.cc
index 8ea994e..c09017a 100644
--- a/components/update_client/update_engine.cc
+++ b/components/update_client/update_engine.cc
@@ -162,9 +162,7 @@
       update_checker_factory_(config_, metadata_.get());
 
   update_context->update_checker->CheckForUpdates(
-      update_context->session_id,
-      update_context->components_to_check_for_updates,
-      update_context->components, config_->ExtraRequestParams(),
+      update_context, config_->ExtraRequestParams(),
       base::BindOnce(&UpdateEngine::UpdateCheckResultsAvailable, this,
                      update_context));
 }
diff --git a/components/viz/service/display/overlay_candidate.cc b/components/viz/service/display/overlay_candidate.cc
index 83c03a64..19f78ce 100644
--- a/components/viz/service/display/overlay_candidate.cc
+++ b/components/viz/service/display/overlay_candidate.cc
@@ -93,39 +93,6 @@
     return gfx::OVERLAY_TRANSFORM_INVALID;
 }
 
-gfx::Rect GetDamageRect(const DrawQuad* quad,
-                        SurfaceDamageRectList* surface_damage_rect_list) {
-  const SharedQuadState* sqs = quad->shared_quad_state;
-  auto& transform = sqs->quad_to_target_transform;
-  gfx::RectF display_rect = gfx::RectF(quad->rect);
-  transform.TransformRect(&display_rect);
-  if (!sqs->overlay_damage_index.has_value()) {
-    gfx::Rect display_rect_int = gfx::ToRoundedRect(display_rect);
-    // This is a special case where an overlay candidate may have damage but it
-    // does not have a damage index since it was not the only quad in the
-    // original surface. Here the union of all |surface_damage_rect_list| will
-    // be in effect the full damage for this display.
-    auto full_display_damage = gfx::Rect();
-    for (auto& each : *surface_damage_rect_list) {
-      full_display_damage.Union(each);
-    }
-
-    // We limit the damage to the candidates quad rect in question.
-    gfx::Rect intersection = display_rect_int;
-    intersection.Intersect(full_display_damage);
-    return intersection;
-  }
-
-  size_t overlay_damage_index = sqs->overlay_damage_index.value();
-  // Invalid index.
-  if (overlay_damage_index >= surface_damage_rect_list->size()) {
-    DCHECK(false);
-    return gfx::Rect();
-  }
-
-  return (*surface_damage_rect_list)[overlay_damage_index];
-}
-
 }  // namespace
 
 OverlayCandidate::OverlayCandidate() = default;
@@ -134,19 +101,13 @@
 
 OverlayCandidate::~OverlayCandidate() = default;
 
-// static
-OverlayCandidate::CandidateStatus OverlayCandidate::FromDrawQuad(
-    DisplayResourceProvider* resource_provider,
-    SurfaceDamageRectList* surface_damage_rect_list,
-    const SkM44& output_color_matrix,
+OverlayCandidate::CandidateStatus OverlayCandidateFactory::FromDrawQuad(
     const DrawQuad* quad,
-    const gfx::RectF& primary_rect,
-    OverlayCandidate* candidate,
-    bool is_delegated_context) {
+    OverlayCandidate& candidate) const {
   // It is currently not possible to set a color conversion matrix on an HW
   // overlay plane.
   // TODO(https://crbug.com/792757): Remove this check once the bug is resolved.
-  if (output_color_matrix != SkM44())
+  if (*output_color_matrix_ != SkM44())
     return CandidateStatus::kFailColorMatrix;
 
   const SharedQuadState* sqs = quad->shared_quad_state;
@@ -154,12 +115,12 @@
   // We don't support an opacity value different than one for an overlay plane.
   // Render pass quads should have their |sqs| opacity integrated directly into
   // their final output buffers.
-  if (!cc::MathUtil::IsWithinEpsilon(sqs->opacity, 1.0f) &&
-      !is_delegated_context) {
+  if (!is_delegated_context_ &&
+      !cc::MathUtil::IsWithinEpsilon(sqs->opacity, 1.0f)) {
     return CandidateStatus::kFailOpacity;
   }
-  candidate->opacity = sqs->opacity;
-  candidate->rounded_corners = sqs->mask_filter_info.rounded_corner_bounds();
+  candidate.opacity = sqs->opacity;
+  candidate.rounded_corners = sqs->mask_filter_info.rounded_corner_bounds();
 
   // We support only kSrc (no blending) and kSrcOver (blending with premul).
   if (!(sqs->blend_mode == SkBlendMode::kSrc ||
@@ -167,43 +128,33 @@
     return CandidateStatus::kFailBlending;
   }
 
-  candidate->requires_overlay =
-      OverlayCandidate::RequiresOverlay(quad);
-  candidate->overlay_damage_index =
-      sqs->overlay_damage_index.value_or(kInvalidDamageIndex);
+  candidate.requires_overlay = OverlayCandidate::RequiresOverlay(quad);
+  candidate.overlay_damage_index =
+      sqs->overlay_damage_index.value_or(OverlayCandidate::kInvalidDamageIndex);
 
   switch (quad->material) {
     case DrawQuad::Material::kTextureContent:
-      return FromTextureQuad(resource_provider, surface_damage_rect_list,
-                             TextureDrawQuad::MaterialCast(quad), primary_rect,
-                             candidate, is_delegated_context);
+      return FromTextureQuad(TextureDrawQuad::MaterialCast(quad), candidate);
     case DrawQuad::Material::kVideoHole:
-      return FromVideoHoleQuad(resource_provider, surface_damage_rect_list,
-                               VideoHoleDrawQuad::MaterialCast(quad),
+      return FromVideoHoleQuad(VideoHoleDrawQuad::MaterialCast(quad),
                                candidate);
     case DrawQuad::Material::kStreamVideoContent:
-      return FromStreamVideoQuad(resource_provider, surface_damage_rect_list,
-                                 StreamVideoDrawQuad::MaterialCast(quad),
-                                 candidate, is_delegated_context, primary_rect);
+      return FromStreamVideoQuad(StreamVideoDrawQuad::MaterialCast(quad),
+                                 candidate);
     case DrawQuad::Material::kSolidColor:
-      if (!is_delegated_context)
+      if (!is_delegated_context_)
         return CandidateStatus::kFailQuadNotSupported;
-      return candidate->FromSolidColorQuad(
-          resource_provider, surface_damage_rect_list,
-          SolidColorDrawQuad::MaterialCast(quad), primary_rect, candidate);
+      return FromSolidColorQuad(SolidColorDrawQuad::MaterialCast(quad),
+                                candidate);
     case DrawQuad::Material::kAggregatedRenderPass:
-      if (!is_delegated_context)
+      if (!is_delegated_context_)
         return CandidateStatus::kFailQuadNotSupported;
-      return candidate->FromAggregateQuad(
-          resource_provider, surface_damage_rect_list,
-          AggregatedRenderPassDrawQuad::MaterialCast(quad), primary_rect,
-          candidate);
+      return FromAggregateQuad(AggregatedRenderPassDrawQuad::MaterialCast(quad),
+                               candidate);
     case DrawQuad::Material::kTiledContent:
-      if (!is_delegated_context)
+      if (!is_delegated_context_)
         return CandidateStatus::kFailQuadNotSupported;
-      return candidate->FromTileQuad(
-          resource_provider, surface_damage_rect_list,
-          TileDrawQuad::MaterialCast(quad), primary_rect, candidate);
+      return FromTileQuad(TileDrawQuad::MaterialCast(quad), candidate);
     default:
       break;
   }
@@ -247,17 +198,52 @@
   return false;
 }
 
-// static
-int OverlayCandidate::EstimateVisibleDamage(
+OverlayCandidateFactory::OverlayCandidateFactory(
+    const AggregatedRenderPass* render_pass,
+    DisplayResourceProvider* resource_provider,
+    const SurfaceDamageRectList* surface_damage_rect_list,
+    const SkM44* output_color_matrix,
+    const gfx::RectF primary_rect,
+    bool is_delegated_context)
+    : render_pass_(render_pass),
+      resource_provider_(resource_provider),
+      surface_damage_rect_list_(surface_damage_rect_list),
+      output_color_matrix_(output_color_matrix),
+      primary_rect_(primary_rect),
+      is_delegated_context_(is_delegated_context) {
+  // TODO(crbug.com/1323002): Replace this set with a simple ordered linear
+  // search when this bug is resolved.
+  base::flat_set<size_t> indices_with_quad_damage;
+  for (auto* sqs : render_pass_->shared_quad_state_list) {
+    // If a |sqs| has a damage index it will only be associated with a single
+    // draw quad.
+    if (sqs->overlay_damage_index.has_value()) {
+      indices_with_quad_damage.insert(sqs->overlay_damage_index.value());
+    }
+  }
+
+  for (size_t i = 0; i < (*surface_damage_rect_list_).size(); i++) {
+    // Add this damage only if it does not correspond to a specific quad.
+    // Ideally any damage that we might want to separate out (think overlays)
+    // will not end up in this |unassigned_surface_damage_| rect.
+    if (!indices_with_quad_damage.contains(i)) {
+      unassigned_surface_damage_.Union((*surface_damage_rect_list_)[i]);
+    }
+  }
+}
+
+OverlayCandidateFactory::~OverlayCandidateFactory() = default;
+
+float OverlayCandidateFactory::EstimateVisibleDamage(
     const DrawQuad* quad,
-    SurfaceDamageRectList* surface_damage_rect_list,
+    const OverlayCandidate& candidate,
     QuadList::ConstIterator quad_list_begin,
-    QuadList::ConstIterator quad_list_end) {
-  gfx::Rect quad_damage = GetDamageRect(quad, surface_damage_rect_list);
-  int occluded_damage_estimate_total = 0;
+    QuadList::ConstIterator quad_list_end) const {
+  gfx::Rect quad_damage = gfx::ToEnclosingRect(GetDamageRect(quad, candidate));
+  float occluded_damage_estimate_total = 0.f;
   for (auto overlap_iter = quad_list_begin; overlap_iter != quad_list_end;
        ++overlap_iter) {
-    gfx::Rect overlap_rect = gfx::ToRoundedRect(cc::MathUtil::MapClippedRect(
+    gfx::Rect overlap_rect = gfx::ToEnclosingRect(cc::MathUtil::MapClippedRect(
         overlap_iter->shared_quad_state->quad_to_target_transform,
         gfx::RectF(overlap_iter->rect)));
 
@@ -273,7 +259,7 @@
   // reason why this computation is an estimate and why we have the max clamping
   // below.
   return std::max(
-      0, quad_damage.size().GetArea() - occluded_damage_estimate_total);
+      0.f, quad_damage.size().GetArea() - occluded_damage_estimate_total);
 }
 
 // static
@@ -295,13 +281,12 @@
   }
 }
 
-// static
-bool OverlayCandidate::IsOccludedByFilteredQuad(
+bool OverlayCandidateFactory::IsOccludedByFilteredQuad(
     const OverlayCandidate& candidate,
     QuadList::ConstIterator quad_list_begin,
     QuadList::ConstIterator quad_list_end,
     const base::flat_map<AggregatedRenderPassId, cc::FilterOperations*>&
-        render_pass_backdrop_filters) {
+        render_pass_backdrop_filters) const {
   for (auto overlap_iter = quad_list_begin; overlap_iter != quad_list_end;
        ++overlap_iter) {
     if (overlap_iter->material == DrawQuad::Material::kAggregatedRenderPass) {
@@ -320,29 +305,24 @@
   return false;
 }
 
-// static
-OverlayCandidate::CandidateStatus OverlayCandidate::FromDrawQuadResource(
-    DisplayResourceProvider* resource_provider,
-    SurfaceDamageRectList* surface_damage_rect_list,
+OverlayCandidate::CandidateStatus OverlayCandidateFactory::FromDrawQuadResource(
     const DrawQuad* quad,
     ResourceId resource_id,
     bool y_flipped,
-    OverlayCandidate* candidate,
-    bool is_delegated_context,
-    const gfx::RectF& primary_rect) {
+    OverlayCandidate& candidate) const {
   if (resource_id != kInvalidResourceId &&
-      !resource_provider->IsOverlayCandidate(resource_id))
+      !resource_provider_->IsOverlayCandidate(resource_id))
     return CandidateStatus::kFailNotOverlay;
 
   if (quad->visible_rect.IsEmpty())
     return CandidateStatus::kFailVisible;
 
   if (resource_id != kInvalidResourceId) {
-    candidate->format = resource_provider->GetBufferFormat(resource_id);
-    candidate->color_space = resource_provider->GetColorSpace(resource_id);
-    candidate->hdr_metadata = resource_provider->GetHDRMetadata(resource_id);
+    candidate.format = resource_provider_->GetBufferFormat(resource_id);
+    candidate.color_space = resource_provider_->GetColorSpace(resource_id);
+    candidate.hdr_metadata = resource_provider_->GetHDRMetadata(resource_id);
 
-    if (!base::Contains(kOverlayFormats, candidate->format))
+    if (!base::Contains(kOverlayFormats, candidate.format))
       return CandidateStatus::kFailBufferFormat;
   }
 
@@ -352,28 +332,28 @@
       GetOverlayTransform(sqs->quad_to_target_transform, y_flipped);
   if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
     return CandidateStatus::kFailNotAxisAligned;
-  candidate->transform = overlay_transform;
+  candidate.transform = overlay_transform;
 
   auto& transform = sqs->quad_to_target_transform;
-  candidate->display_rect = gfx::RectF(quad->rect);
-  transform.TransformRect(&candidate->display_rect);
+  candidate.display_rect = gfx::RectF(quad->rect);
+  transform.TransformRect(&candidate.display_rect);
 
-  candidate->clip_rect = sqs->clip_rect;
-  candidate->is_opaque =
+  candidate.clip_rect = sqs->clip_rect;
+  candidate.is_opaque =
       !quad->ShouldDrawWithBlendingForReasonOtherThanMaskFilter();
-  candidate->has_mask_filter = !sqs->mask_filter_info.IsEmpty();
+  candidate.has_mask_filter = !sqs->mask_filter_info.IsEmpty();
 
   if (resource_id != kInvalidResourceId) {
-    candidate->resource_size_in_pixels =
-        resource_provider->GetResourceBackedSize(resource_id);
+    candidate.resource_size_in_pixels =
+        resource_provider_->GetResourceBackedSize(resource_id);
   } else {
-    candidate->resource_size_in_pixels =
-        gfx::Size(candidate->display_rect.size().width(),
-                  candidate->display_rect.size().height());
+    candidate.resource_size_in_pixels =
+        gfx::Size(candidate.display_rect.size().width(),
+                  candidate.display_rect.size().height());
   }
 
-  AssignDamage(quad, surface_damage_rect_list, candidate);
-  candidate->resource_id = resource_id;
+  AssignDamage(quad, candidate);
+  candidate.resource_id = resource_id;
 
   struct TrackingIdData {
     gfx::Rect rect;
@@ -382,129 +362,105 @@
 
   TrackingIdData track_data{quad->rect, FrameSinkId()};
   if (resource_id != kInvalidResourceId) {
-    candidate->mailbox = resource_provider->GetMailbox(resource_id);
+    candidate.mailbox = resource_provider_->GetMailbox(resource_id);
     track_data.frame_sink_id =
-        resource_provider->GetSurfaceId(resource_id).frame_sink_id();
+        resource_provider_->GetSurfaceId(resource_id).frame_sink_id();
   }
 
   // Delegated compositing does not yet support |clip_rect| so it is applied
   // here to the |display_rect| and |uv_rect| directly.
-  if (is_delegated_context) {
-    if (candidate->clip_rect.has_value())
-      ApplyClip(candidate, gfx::RectF(*candidate->clip_rect));
+
+  if (is_delegated_context_) {
+    if (candidate.clip_rect.has_value())
+      OverlayCandidate::ApplyClip(candidate, gfx::RectF(*candidate.clip_rect));
 
     if (quad->visible_rect != quad->rect) {
       auto visible_rect = gfx::RectF(quad->visible_rect);
       transform.TransformRect(&visible_rect);
-      ApplyClip(candidate, gfx::RectF(visible_rect));
+      OverlayCandidate::ApplyClip(candidate, gfx::RectF(visible_rect));
     }
     // TODO(https://crbug.com/1300552) : Tile quads can overlay other quads and
     // the window by one pixel. Exo does not yet clip these quads so we need to
     // clip here with the |primary_rect|.
-    ApplyClip(candidate, primary_rect);
+    OverlayCandidate::ApplyClip(candidate, primary_rect_);
 
-    if (candidate->display_rect.IsEmpty())
+    if (candidate.display_rect.IsEmpty())
       return CandidateStatus::kFailVisible;
   }
 
-  candidate->tracking_id = base::Hash(&track_data, sizeof(track_data));
+  candidate.tracking_id = base::Hash(&track_data, sizeof(track_data));
   return CandidateStatus::kSuccess;
 }
 
-// static
-OverlayCandidate::CandidateStatus OverlayCandidate::FromAggregateQuad(
-    DisplayResourceProvider* resource_provider,
-    SurfaceDamageRectList* surface_damage_rect_list,
+OverlayCandidate::CandidateStatus OverlayCandidateFactory::FromAggregateQuad(
     const AggregatedRenderPassDrawQuad* quad,
-    const gfx::RectF& primary_rect,
-    OverlayCandidate* candidate) {
-  auto rtn = FromDrawQuadResource(resource_provider, surface_damage_rect_list,
-                                  quad, kInvalidResourceId, false, candidate,
-                                  true, primary_rect);
+    OverlayCandidate& candidate) const {
+  auto rtn = FromDrawQuadResource(quad, kInvalidResourceId, false, candidate);
   if (rtn == CandidateStatus::kSuccess) {
-    candidate->rpdq = quad;
+    candidate.rpdq = quad;
   }
   return rtn;
 }
 
-// static
-OverlayCandidate::CandidateStatus OverlayCandidate::FromSolidColorQuad(
-    DisplayResourceProvider* resource_provider,
-    SurfaceDamageRectList* surface_damage_rect_list,
+OverlayCandidate::CandidateStatus OverlayCandidateFactory::FromSolidColorQuad(
     const SolidColorDrawQuad* quad,
-    const gfx::RectF& primary_rect,
-    OverlayCandidate* candidate) {
-  auto rtn = FromDrawQuadResource(resource_provider, surface_damage_rect_list,
-                                  quad, kInvalidResourceId, false, candidate,
-                                  true, primary_rect);
+    OverlayCandidate& candidate) const {
+  auto rtn = FromDrawQuadResource(quad, kInvalidResourceId, false, candidate);
 
   if (rtn == CandidateStatus::kSuccess) {
-    candidate->color = quad->color;
+    candidate.color = quad->color;
     // Mark this candidate a solid color as the |color| member can be either a
     // background of the overlay or a color of the solid color quad.
-    candidate->is_solid_color = true;
+    candidate.is_solid_color = true;
   }
   return rtn;
 }
 
-// static
-// For VideoHoleDrawQuad, only calculate geometry information
-// and put it in the |candidate|.
-OverlayCandidate::CandidateStatus OverlayCandidate::FromVideoHoleQuad(
-    DisplayResourceProvider* resource_provider,
-    SurfaceDamageRectList* surface_damage_rect_list,
+// For VideoHoleDrawQuad, only calculate geometry information and put it in the
+// |candidate|.
+OverlayCandidate::CandidateStatus OverlayCandidateFactory::FromVideoHoleQuad(
     const VideoHoleDrawQuad* quad,
-    OverlayCandidate* candidate) {
+    OverlayCandidate& candidate) const {
   gfx::OverlayTransform overlay_transform = GetOverlayTransform(
       quad->shared_quad_state->quad_to_target_transform, false);
   if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
     return CandidateStatus::kFailNotAxisAligned;
 
   auto& transform = quad->shared_quad_state->quad_to_target_transform;
-  candidate->display_rect = gfx::RectF(quad->rect);
-  transform.TransformRect(&candidate->display_rect);
-  candidate->transform = overlay_transform;
-  candidate->is_opaque =
+  candidate.display_rect = gfx::RectF(quad->rect);
+  transform.TransformRect(&candidate.display_rect);
+  candidate.transform = overlay_transform;
+  candidate.is_opaque =
       !quad->ShouldDrawWithBlendingForReasonOtherThanMaskFilter();
-  candidate->has_mask_filter =
+  candidate.has_mask_filter =
       !quad->shared_quad_state->mask_filter_info.IsEmpty();
 
-  AssignDamage(quad, surface_damage_rect_list, candidate);
-  candidate->tracking_id = base::FastHash(quad->overlay_plane_id.AsBytes());
+  AssignDamage(quad, candidate);
+  candidate.tracking_id = base::FastHash(quad->overlay_plane_id.AsBytes());
 
   return CandidateStatus::kSuccess;
 }
 
-OverlayCandidate::CandidateStatus OverlayCandidate::FromTileQuad(
-    DisplayResourceProvider* resource_provider,
-    SurfaceDamageRectList* surface_damage_rect_list,
+OverlayCandidate::CandidateStatus OverlayCandidateFactory::FromTileQuad(
     const TileDrawQuad* quad,
-    const gfx::RectF& primary_rect,
-    OverlayCandidate* candidate) {
+    OverlayCandidate& candidate) const {
   if (quad->nearest_neighbor)
     return CandidateStatus::kFailNearFilter;
 
-  candidate->resource_size_in_pixels =
-      resource_provider->GetResourceBackedSize(quad->resource_id());
-  candidate->uv_rect = gfx::ScaleRect(
-      quad->tex_coord_rect, 1.f / candidate->resource_size_in_pixels.width(),
-      1.f / candidate->resource_size_in_pixels.height());
+  candidate.resource_size_in_pixels =
+      resource_provider_->GetResourceBackedSize(quad->resource_id());
+  candidate.uv_rect = gfx::ScaleRect(
+      quad->tex_coord_rect, 1.f / candidate.resource_size_in_pixels.width(),
+      1.f / candidate.resource_size_in_pixels.height());
 
-  auto rtn = FromDrawQuadResource(resource_provider, surface_damage_rect_list,
-                                  quad, quad->resource_id(), false, candidate,
-                                  true, primary_rect);
+  auto rtn = FromDrawQuadResource(quad, quad->resource_id(), false, candidate);
   return rtn;
 }
 
-// static
-OverlayCandidate::CandidateStatus OverlayCandidate::FromTextureQuad(
-    DisplayResourceProvider* resource_provider,
-    SurfaceDamageRectList* surface_damage_rect_list,
+OverlayCandidate::CandidateStatus OverlayCandidateFactory::FromTextureQuad(
     const TextureDrawQuad* quad,
-    const gfx::RectF& primary_rect,
-    OverlayCandidate* candidate,
-    bool is_delegated_context) {
-  if (!is_delegated_context &&
+    OverlayCandidate& candidate) const {
+  if (!is_delegated_context_ &&
       quad->overlay_priority_hint == OverlayPriority::kLow) {
     // For current implementation low priority means this does not promote to
     // overlay.
@@ -520,91 +476,81 @@
     // This path can also be used by other platforms like Ash/Chrome, which does
     // not support overlays with background color. Only LaCros/Wayland supports
     // that.
-    if (!is_delegated_context)
+    if (!is_delegated_context_)
       return CandidateStatus::kFailBlending;
-    candidate->color = quad->background_color;
+    candidate.color = quad->background_color;
   }
 
-  candidate->uv_rect = BoundingRect(quad->uv_top_left, quad->uv_bottom_right);
+  candidate.uv_rect = BoundingRect(quad->uv_top_left, quad->uv_bottom_right);
 
-  auto rtn = FromDrawQuadResource(
-      resource_provider, surface_damage_rect_list, quad, quad->resource_id(),
-      quad->y_flipped, candidate, is_delegated_context, primary_rect);
+  auto rtn = FromDrawQuadResource(quad, quad->resource_id(), quad->y_flipped,
+                                  candidate);
   if (rtn == CandidateStatus::kSuccess) {
     // Only handle clip rect for required overlays
-    if (!is_delegated_context && candidate->requires_overlay)
-      HandleClipAndSubsampling(candidate, primary_rect);
+    if (!is_delegated_context_ && candidate.requires_overlay)
+      HandleClipAndSubsampling(candidate);
 
     // Texture quads for UI elements like scroll bars have empty
     // |size_in_pixels| as 'set_resource_size_in_pixels' is not called as these
     // quads are not intended to become overlays.
     if (!quad->resource_size_in_pixels().IsEmpty())
-      candidate->priority_hint = gfx::OverlayPriorityHint::kRegular;
+      candidate.priority_hint = gfx::OverlayPriorityHint::kRegular;
   }
   return rtn;
 }
 
-// static
-OverlayCandidate::CandidateStatus OverlayCandidate::FromStreamVideoQuad(
-    DisplayResourceProvider* resource_provider,
-    SurfaceDamageRectList* surface_damage_rect_list,
+OverlayCandidate::CandidateStatus OverlayCandidateFactory::FromStreamVideoQuad(
     const StreamVideoDrawQuad* quad,
-    OverlayCandidate* candidate,
-    bool is_delegated_context,
-    const gfx::RectF& primary_rect) {
-  auto rtn = FromDrawQuadResource(resource_provider, surface_damage_rect_list,
-                                  quad, quad->resource_id(), false, candidate,
-                                  is_delegated_context, primary_rect);
+    OverlayCandidate& candidate) const {
+  auto rtn = FromDrawQuadResource(quad, quad->resource_id(), false, candidate);
 
   if (rtn == CandidateStatus::kSuccess) {
-    candidate->resource_size_in_pixels = quad->resource_size_in_pixels();
-    candidate->uv_rect = BoundingRect(quad->uv_top_left, quad->uv_bottom_right);
+    candidate.resource_size_in_pixels = quad->resource_size_in_pixels();
+    candidate.uv_rect = BoundingRect(quad->uv_top_left, quad->uv_bottom_right);
 #if BUILDFLAG(IS_ANDROID)
-    candidate->is_backed_by_surface_texture =
-        resource_provider->IsBackedBySurfaceTexture(quad->resource_id());
+    candidate.is_backed_by_surface_texture =
+        resource_provider_->IsBackedBySurfaceTexture(quad->resource_id());
 #endif
   }
   return rtn;
 }
 
-// static
-void OverlayCandidate::HandleClipAndSubsampling(
-    OverlayCandidate* candidate,
-    const gfx::RectF& primary_rect) {
+void OverlayCandidateFactory::HandleClipAndSubsampling(
+    OverlayCandidate& candidate) const {
   // The purpose of this is to enable overlays that are required (i.e. protected
   // content) to be able to be shown in all cases. This will allow them to pass
   // the clipping check and also the 2x alignment requirement for subsampling in
   // the Intel DRM driver. This should not be used in cases where the surface
   // will not always be promoted to an overlay as it will lead to shifting of
   // the content when it switches between composition and overlay.
-  if (!candidate->clip_rect)
+  if (!candidate.clip_rect)
     return;
 
   // Make sure it's in a format we can deal with, we only support YUV and P010.
-  if (candidate->format != gfx::BufferFormat::YUV_420_BIPLANAR &&
-      candidate->format != gfx::BufferFormat::P010) {
+  if (candidate.format != gfx::BufferFormat::YUV_420_BIPLANAR &&
+      candidate.format != gfx::BufferFormat::P010) {
     return;
   }
   // Clip the clip rect to the primary plane. An overlay will only be shown on
   // a single display, so we want to perform our calculations within the bounds
   // of that display.
-  if (!primary_rect.IsEmpty())
-    candidate->clip_rect->Intersect(gfx::ToNearestRect(primary_rect));
+  if (!primary_rect_.IsEmpty())
+    candidate.clip_rect->Intersect(gfx::ToNearestRect(primary_rect_));
 
   // Calculate |uv_rect| of |clip_rect| in |display_rect|
   gfx::RectF uv_rect = cc::MathUtil::ScaleRectProportional(
-      candidate->uv_rect, candidate->display_rect,
-      gfx::RectF(*candidate->clip_rect));
+      candidate.uv_rect, candidate.display_rect,
+      gfx::RectF(*candidate.clip_rect));
 
   // In case that |uv_rect| of candidate is not (0, 0, 1, 1)
-  candidate->uv_rect.Intersect(uv_rect);
+  candidate.uv_rect.Intersect(uv_rect);
 
   // Update |display_rect| to avoid unexpected scaling and the candidate should
   // not be regarded as clippped after this.
-  candidate->display_rect.Intersect(gfx::RectF(*candidate->clip_rect));
-  candidate->clip_rect.reset();
-  gfx::Rect rounded_display_rect = gfx::ToRoundedRect(candidate->display_rect);
-  candidate->display_rect.SetRect(
+  candidate.display_rect.Intersect(gfx::RectF(*candidate.clip_rect));
+  candidate.clip_rect.reset();
+  gfx::Rect rounded_display_rect = gfx::ToRoundedRect(candidate.display_rect);
+  candidate.display_rect.SetRect(
       rounded_display_rect.x(), rounded_display_rect.y(),
       rounded_display_rect.width(), rounded_display_rect.height());
 
@@ -613,8 +559,8 @@
 
   // Get the rect for the source coordinates.
   gfx::RectF src_rect = gfx::ScaleRect(
-      candidate->uv_rect, candidate->resource_size_in_pixels.width(),
-      candidate->resource_size_in_pixels.height());
+      candidate.uv_rect, candidate.resource_size_in_pixels.width(),
+      candidate.resource_size_in_pixels.height());
   // Make it an integral multiple of the subsampling factor.
   auto subsample_round = [](float val) {
     constexpr int kSubsamplingFactor = 2;
@@ -626,19 +572,16 @@
   src_rect.set_width(subsample_round(src_rect.width()));
   src_rect.set_height(subsample_round(src_rect.height()));
   // Scale it back into UV space and set it in the candidate.
-  candidate->uv_rect = gfx::ScaleRect(
-      src_rect, 1.0f / candidate->resource_size_in_pixels.width(),
-      1.0f / candidate->resource_size_in_pixels.height());
+  candidate.uv_rect =
+      gfx::ScaleRect(src_rect, 1.0f / candidate.resource_size_in_pixels.width(),
+                     1.0f / candidate.resource_size_in_pixels.height());
 }
 
-// static
-void OverlayCandidate::AssignDamage(
-    const DrawQuad* quad,
-    SurfaceDamageRectList* surface_damage_rect_list,
-    OverlayCandidate* candidate) {
+void OverlayCandidateFactory::AssignDamage(const DrawQuad* quad,
+                                           OverlayCandidate& candidate) const {
   auto& transform = quad->shared_quad_state->quad_to_target_transform;
-  const auto damage_rect = GetDamageRect(quad, surface_damage_rect_list);
-  auto transformed_damage = gfx::RectF(damage_rect);
+  auto damage_rect = GetDamageRect(quad, candidate);
+  auto transformed_damage = damage_rect;
   gfx::Transform inv;
   if (transform.GetInverse(&inv)) {
     inv.TransformRect(&transformed_damage);
@@ -657,37 +600,65 @@
 
     // The normalization above is not enough if the |uv_rect| is not 0,0-1x1.
     // This is because texture uvs can effectively magnify damage.
-    if (!candidate->uv_rect.IsEmpty()) {
-      transformed_damage.Scale(candidate->uv_rect.width(),
-                               candidate->uv_rect.height());
-      transformed_damage.Offset(candidate->uv_rect.OffsetFromOrigin());
+    if (!candidate.uv_rect.IsEmpty()) {
+      transformed_damage.Scale(candidate.uv_rect.width(),
+                               candidate.uv_rect.height());
+      transformed_damage.Offset(candidate.uv_rect.OffsetFromOrigin());
     }
 
     // Buffer damage is in texels not UVs so scale by resource size.
-    transformed_damage.Scale(candidate->resource_size_in_pixels.width(),
-                             candidate->resource_size_in_pixels.height());
+    transformed_damage.Scale(candidate.resource_size_in_pixels.width(),
+                             candidate.resource_size_in_pixels.height());
   } else {
     // If not invertible, set to full damage.
     // TODO(https://crbug.com/1279965): |resource_size_in_pixels| might not be
     // properly initialized at this stage.
     transformed_damage =
-        gfx::RectF(gfx::SizeF(candidate->resource_size_in_pixels));
+        gfx::RectF(gfx::SizeF(candidate.resource_size_in_pixels));
   }
   // For underlays the function 'EstimateVisibleDamage()' is called to update
   // |damage_area_estimate| to more accurately reflect the actual visible
   // damage.
-  candidate->damage_area_estimate = damage_rect.size().GetArea();
-  candidate->damage_rect = transformed_damage;
+  candidate.damage_area_estimate = damage_rect.size().GetArea();
+  candidate.damage_rect = transformed_damage;
 }
 
-void OverlayCandidate::ApplyClip(OverlayCandidate* candidate,
+// static
+void OverlayCandidate::ApplyClip(OverlayCandidate& candidate,
                                  const gfx::RectF& clip_rect) {
-  gfx::RectF intersect_clip_display = clip_rect;
-  intersect_clip_display.Intersect(candidate->display_rect);
-  gfx::RectF uv_rect = cc::MathUtil::ScaleRectProportional(
-      candidate->uv_rect, candidate->display_rect, intersect_clip_display);
-  candidate->display_rect = intersect_clip_display;
-  candidate->uv_rect = uv_rect;
+  if (!clip_rect.Contains(candidate.display_rect)) {
+    gfx::RectF intersect_clip_display = clip_rect;
+    intersect_clip_display.Intersect(candidate.display_rect);
+    gfx::RectF uv_rect = cc::MathUtil::ScaleRectProportional(
+        candidate.uv_rect, candidate.display_rect, intersect_clip_display);
+    candidate.display_rect = intersect_clip_display;
+    candidate.uv_rect = uv_rect;
+  }
+}
+
+gfx::RectF OverlayCandidateFactory::GetDamageRect(
+    const DrawQuad* quad,
+    const OverlayCandidate& candidate) const {
+  const SharedQuadState* sqs = quad->shared_quad_state;
+  if (!sqs->overlay_damage_index.has_value()) {
+    // This is a special case where an overlay candidate may have damage but it
+    // does not have a damage index since it was not the only quad in the
+    // original surface. Here the |unassigned_surface_damage_| will contain all
+    // unassigned damage and we use it to conservatively estimate the damage for
+    // this quad. We limit the damage to the candidates quad rect in question.
+    gfx::RectF intersection = candidate.display_rect;
+    intersection.Intersect(gfx::RectF(unassigned_surface_damage_));
+    return intersection;
+  }
+
+  size_t overlay_damage_index = sqs->overlay_damage_index.value();
+  // Invalid index.
+  if (overlay_damage_index >= surface_damage_rect_list_->size()) {
+    DCHECK(false);
+    return gfx::RectF();
+  }
+
+  return gfx::RectF((*surface_damage_rect_list_)[overlay_damage_index]);
 }
 
 }  // namespace viz
diff --git a/components/viz/service/display/overlay_candidate.h b/components/viz/service/display/overlay_candidate.h
index 00bd838..bf3213f 100644
--- a/components/viz/service/display/overlay_candidate.h
+++ b/components/viz/service/display/overlay_candidate.h
@@ -60,17 +60,6 @@
   using TrackingId = uint32_t;
   static constexpr TrackingId kDefaultTrackingId{0};
 
-  // Returns true and fills in |candidate| if |draw_quad| is of a known quad
-  // type and contains an overlayable resource. |primary_rect| can be empty in
-  // the case of a null primary plane.
-  static CandidateStatus FromDrawQuad(
-      DisplayResourceProvider* resource_provider,
-      SurfaceDamageRectList* surface_damage_rect_list,
-      const SkM44& output_color_matrix,
-      const DrawQuad* quad,
-      const gfx::RectF& primary_rect,
-      OverlayCandidate* candidate,
-      bool is_delegated_context = false);
   // Returns true if |quad| will not block quads underneath from becoming
   // an overlay.
   static bool IsInvisibleQuad(const DrawQuad* quad);
@@ -81,25 +70,11 @@
                          QuadList::ConstIterator quad_list_begin,
                          QuadList::ConstIterator quad_list_end);
 
-  // Returns an estimate of this |quad|'s actual visible damage area. This
-  // visible damage is computed by combining from input
-  // |surface_damage_rect_list| with the occluding rects in the quad_list.
-  // This is an estimate since the occluded damage area is calculated on a per
-  // quad basis.
-  static int EstimateVisibleDamage(
-      const DrawQuad* quad,
-      SurfaceDamageRectList* surface_damage_rect_list,
-      QuadList::ConstIterator quad_list_begin,
-      QuadList::ConstIterator quad_list_end);
-
-  // Returns true if any of the quads in the list given by |quad_list_begin|
-  // and |quad_list_end| have a filter associated and occlude |candidate|.
-  static bool IsOccludedByFilteredQuad(
-      const OverlayCandidate& candidate,
-      QuadList::ConstIterator quad_list_begin,
-      QuadList::ConstIterator quad_list_end,
-      const base::flat_map<AggregatedRenderPassId, cc::FilterOperations*>&
-          render_pass_backdrop_filters);
+  // Modifies the |candidate|'s |display_rect| to be clipped within |clip_rect|.
+  // This function will also update the |uv_rect| based on what clipping was
+  // applied to |display_rect|.
+  static void ApplyClip(OverlayCandidate& candidate,
+                        const gfx::RectF& clip_rect);
 
   // Returns true if the |quad| cannot be displayed on the main plane. This is
   // used in conjuction with protected content that can't be GPU composited and
@@ -163,7 +138,7 @@
 
   // The total area in square pixels of damage for this candidate's quad. This
   // is an estimate when 'EstimateOccludedDamage' function is used.
-  int damage_area_estimate = 0;
+  float damage_area_estimate = 0.f;
 
   // Damage in buffer space (extents bound by |resource_size_in_pixels|).
   gfx::RectF damage_rect;
@@ -211,72 +186,103 @@
   // surface and have the same |DrawQuad::rect| they will have the same
   // |tracking_id|.
   TrackingId tracking_id = kDefaultTrackingId;
-
- private:
-  static CandidateStatus FromDrawQuadResource(
-      DisplayResourceProvider* resource_provider,
-      SurfaceDamageRectList* surface_damage_rect_list,
-      const DrawQuad* quad,
-      ResourceId resource_id,
-      bool y_flipped,
-      OverlayCandidate* candidate,
-      bool is_delegated_context,
-      const gfx::RectF& primary_rect);
-
-  static CandidateStatus FromTextureQuad(
-      DisplayResourceProvider* resource_provider,
-      SurfaceDamageRectList* surface_damage_rect_list,
-      const TextureDrawQuad* quad,
-      const gfx::RectF& primary_rect,
-      OverlayCandidate* candidate,
-      bool is_delegated_context);
-
-  static CandidateStatus FromTileQuad(
-      DisplayResourceProvider* resource_provider,
-      SurfaceDamageRectList* surface_damage_rect_list,
-      const TileDrawQuad* quad,
-      const gfx::RectF& primary_rect,
-      OverlayCandidate* candidate);
-
-  static CandidateStatus FromAggregateQuad(
-      DisplayResourceProvider* resource_provider,
-      SurfaceDamageRectList* surface_damage_rect_list,
-      const AggregatedRenderPassDrawQuad* quad,
-      const gfx::RectF& primary_rect,
-      OverlayCandidate* candidate);
-
-  static CandidateStatus FromSolidColorQuad(
-      DisplayResourceProvider* resource_provider,
-      SurfaceDamageRectList* surface_damage_rect_list,
-      const SolidColorDrawQuad* quad,
-      const gfx::RectF& primary_rect,
-      OverlayCandidate* candidate);
-
-  static CandidateStatus FromStreamVideoQuad(
-      DisplayResourceProvider* resource_provider,
-      SurfaceDamageRectList* surface_damage_rect_list,
-      const StreamVideoDrawQuad* quad,
-      OverlayCandidate* candidate,
-      bool is_delegated_context,
-      const gfx::RectF& primary_rect);
-
-  static CandidateStatus FromVideoHoleQuad(
-      DisplayResourceProvider* resource_provider,
-      SurfaceDamageRectList* surface_damage_rect_list,
-      const VideoHoleDrawQuad* quad,
-      OverlayCandidate* candidate);
-  static void HandleClipAndSubsampling(OverlayCandidate* candidate,
-                                       const gfx::RectF& primary_rect);
-  static void AssignDamage(const DrawQuad* quad,
-                           SurfaceDamageRectList* surface_damage_rect_list,
-                           OverlayCandidate* candidate);
-
-  static void ApplyClip(OverlayCandidate* candidate,
-                        const gfx::RectF& clip_rect);
 };
 
 using OverlayCandidateList = std::vector<OverlayCandidate>;
 
+// This is a factory to help with the creation of |OverlayCandidates|.  On
+// construction, this factory captures the required objects to create candidates
+// from a draw quad.  Common computations for all possible candidates can be
+// made at construction time. This class is const after construction and not
+// copy/moveable to avoid capture ownership issues.
+class VIZ_SERVICE_EXPORT OverlayCandidateFactory {
+ public:
+  using CandidateStatus = OverlayCandidate::CandidateStatus;
+
+  OverlayCandidateFactory(const AggregatedRenderPass* render_pass,
+                          DisplayResourceProvider* resource_provider,
+                          const SurfaceDamageRectList* surface_damage_rect_list,
+                          const SkM44* output_color_matrix,
+                          const gfx::RectF primary_rect,
+                          bool is_delegated_context = false);
+
+  OverlayCandidateFactory(const OverlayCandidateFactory&) = delete;
+  OverlayCandidateFactory& operator=(const OverlayCandidateFactory&) = delete;
+
+  ~OverlayCandidateFactory();
+
+  // Returns |kSuccess| and fills in |candidate| if |draw_quad| is of a known
+  // quad type and contains an overlayable resource. |primary_rect| can be empty
+  // in the case of a null primary plane. |candidate| is expected to be a
+  // freshly constructed |OverlayCandidate| object.
+  CandidateStatus FromDrawQuad(const DrawQuad* quad,
+                               OverlayCandidate& candidate) const;
+
+  // Returns an estimate of this |quad|'s actual visible damage area as float
+  // pixels squared. This visible damage is computed by combining from input
+  // |surface_damage_rect_list_| with the occluding rects in the quad_list. This
+  // is an estimate since the occluded damage area is calculated on a per quad
+  // basis. The |quad_list_begin| and |quad_list_end| provide the range of valid
+  // occluders of this |candidate|.
+  // TODO(petermcneeley): Can we replace this with |visible_rect| in |DrawQuad|?
+  float EstimateVisibleDamage(const DrawQuad* quad,
+                              const OverlayCandidate& candidate,
+                              QuadList::ConstIterator quad_list_begin,
+                              QuadList::ConstIterator quad_list_end) const;
+
+  // Returns true if any of the quads in the list given by |quad_list_begin|
+  // and |quad_list_end| have an associated filter and occlude |candidate|.
+  bool IsOccludedByFilteredQuad(
+      const OverlayCandidate& candidate,
+      QuadList::ConstIterator quad_list_begin,
+      QuadList::ConstIterator quad_list_end,
+      const base::flat_map<AggregatedRenderPassId, cc::FilterOperations*>&
+          render_pass_backdrop_filters) const;
+
+ private:
+  CandidateStatus FromDrawQuadResource(const DrawQuad* quad,
+                                       ResourceId resource_id,
+                                       bool y_flipped,
+                                       OverlayCandidate& candidate) const;
+
+  CandidateStatus FromTextureQuad(const TextureDrawQuad* quad,
+                                  OverlayCandidate& candidate) const;
+
+  CandidateStatus FromTileQuad(const TileDrawQuad* quad,
+                               OverlayCandidate& candidate) const;
+
+  CandidateStatus FromAggregateQuad(const AggregatedRenderPassDrawQuad* quad,
+                                    OverlayCandidate& candidate) const;
+
+  CandidateStatus FromSolidColorQuad(const SolidColorDrawQuad* quad,
+                                     OverlayCandidate& candidate) const;
+
+  CandidateStatus FromStreamVideoQuad(const StreamVideoDrawQuad* quad,
+                                      OverlayCandidate& candidate) const;
+
+  CandidateStatus FromVideoHoleQuad(const VideoHoleDrawQuad* quad,
+                                    OverlayCandidate& candidate) const;
+
+  void HandleClipAndSubsampling(OverlayCandidate& candidate) const;
+
+  void AssignDamage(const DrawQuad* quad, OverlayCandidate& candidate) const;
+
+  // Damage returned from this function is in target content space.
+  gfx::RectF GetDamageRect(const DrawQuad* quad,
+                           const OverlayCandidate& candidate) const;
+
+  const AggregatedRenderPass* render_pass_;
+  DisplayResourceProvider* resource_provider_;
+  const SurfaceDamageRectList* surface_damage_rect_list_;
+  const SkM44* output_color_matrix_;
+  const gfx::RectF primary_rect_;
+  bool is_delegated_context_;
+
+  // The union of all surface damages that are not specifically assigned to a
+  // draw quad.
+  gfx::Rect unassigned_surface_damage_;
+};
+
 }  // namespace viz
 
 #endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_CANDIDATE_H_
diff --git a/components/viz/service/display/overlay_processor_delegated.cc b/components/viz/service/display/overlay_processor_delegated.cc
index 5db5528..b124668 100644
--- a/components/viz/service/display/overlay_processor_delegated.cc
+++ b/components/viz/service/display/overlay_processor_delegated.cc
@@ -134,6 +134,11 @@
       !render_pass_backdrop_filters.empty())
     return false;
 
+  OverlayCandidateFactory candidate_factory = OverlayCandidateFactory(
+      render_pass, resource_provider, surface_damage_rect_list,
+      &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane),
+      is_delegated_context);
+
   std::vector<QuadList::Iterator> candidate_quads;
   int num_quads_skipped = 0;
   for (auto it = quad_list->begin(); it != quad_list->end(); ++it) {
@@ -146,10 +151,7 @@
         gfx::Vector2dF(display_rect.origin().x(), display_rect.origin().y()),
         base::StringPrintf("m=%d rid=%d", static_cast<int>(it->material),
                            it->resources.begin()->value()));
-    auto candidate_status = OverlayCandidate::FromDrawQuad(
-        resource_provider, surface_damage_rect_list, output_color_matrix, *it,
-        GetPrimaryPlaneDisplayRect(primary_plane), &candidate,
-        is_delegated_context);
+    auto candidate_status = candidate_factory.FromDrawQuad(*it, candidate);
     if (candidate_status == OverlayCandidate::CandidateStatus::kSuccess) {
       if (it->material == DrawQuad::Material::kSolidColor) {
         DBG_DRAW_RECT("delegated.overlay.color", candidate.display_rect);
@@ -198,6 +200,8 @@
       candidates->clear();
       delegated_status_ = DelegationStatus::kCompositedCheckOverlayFail;
       DBG_DRAW_RECT("delegated.handled.failed", each.display_rect);
+      DBG_LOG("delegated.handled.failed", "Handled failed %s",
+              each.display_rect.ToString().c_str());
       return false;
     }
   }
diff --git a/components/viz/service/display/overlay_processor_using_strategy.cc b/components/viz/service/display/overlay_processor_using_strategy.cc
index ac3ad8f..ea2192c 100644
--- a/components/viz/service/display/overlay_processor_using_strategy.cc
+++ b/components/viz/service/display/overlay_processor_using_strategy.cc
@@ -413,7 +413,7 @@
     const auto& status = it.second;
     if (status.plane_z_order != 0) {
       RecordOverlayDamageRectHistograms(status.plane_z_order > 0,
-                                        status.damage_area_estimate != 0,
+                                        status.damage_area_estimate != 0.f,
                                         damage_rect.IsEmpty());
     }
   }
@@ -496,11 +496,11 @@
     // for low latency surfaces (inking like in the google keeps application).
     const bool force_update = it->candidate.overlay_damage_index !=
                                   OverlayCandidate::kInvalidDamageIndex &&
-                              it->candidate.damage_area_estimate != 0;
-    track_data.AddRecord(
-        frame_sequence_number_,
-        static_cast<float>(it->candidate.damage_area_estimate) / display_area,
-        it->candidate.resource_id, tracker_config_, force_update);
+                              it->candidate.damage_area_estimate != 0.f;
+    track_data.AddRecord(frame_sequence_number_,
+                         it->candidate.damage_area_estimate / display_area,
+                         it->candidate.resource_id, tracker_config_,
+                         force_update);
     // Here a series of criteria are considered for wholesale rejection of a
     // candidate. The rational for rejection is usually power improvements but
     // this can indirectly reallocate limited overlay resources to another
diff --git a/components/viz/service/display/overlay_processor_using_strategy.h b/components/viz/service/display/overlay_processor_using_strategy.h
index 0a76a92b..e355e7e 100644
--- a/components/viz/service/display/overlay_processor_using_strategy.h
+++ b/components/viz/service/display/overlay_processor_using_strategy.h
@@ -154,7 +154,7 @@
     gfx::Rect overlay_rect;
     gfx::RectF damage_rect;
     uint32_t damage_index;
-    int damage_area_estimate;
+    float damage_area_estimate;
     bool has_mask_filter;
     int plane_z_order;
     bool is_underlay;
diff --git a/components/viz/service/display/overlay_strategy_fullscreen.cc b/components/viz/service/display/overlay_strategy_fullscreen.cc
index 9deafb0..8899c3e 100644
--- a/components/viz/service/display/overlay_strategy_fullscreen.cc
+++ b/components/viz/service/display/overlay_strategy_fullscreen.cc
@@ -51,10 +51,11 @@
     return false;
 
   OverlayCandidate candidate;
-  if (OverlayCandidate::FromDrawQuad(
-          resource_provider, surface_damage_rect_list, output_color_matrix,
-          quad, GetPrimaryPlaneDisplayRect(primary_plane),
-          &candidate) != OverlayCandidate::CandidateStatus::kSuccess) {
+  OverlayCandidateFactory candidate_factory = OverlayCandidateFactory(
+      render_pass, resource_provider, surface_damage_rect_list,
+      &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane));
+  if (candidate_factory.FromDrawQuad(quad, candidate) !=
+      OverlayCandidate::CandidateStatus::kSuccess) {
     return false;
   }
 
@@ -108,10 +109,11 @@
     return;
 
   OverlayCandidate candidate;
-  if (OverlayCandidate::FromDrawQuad(
-          resource_provider, surface_damage_rect_list, output_color_matrix,
-          quad, GetPrimaryPlaneDisplayRect(primary_plane),
-          &candidate) != OverlayCandidate::CandidateStatus::kSuccess) {
+  OverlayCandidateFactory candidate_factory = OverlayCandidateFactory(
+      render_pass, resource_provider, surface_damage_rect_list,
+      &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane));
+  if (candidate_factory.FromDrawQuad(quad, candidate) !=
+      OverlayCandidate::CandidateStatus::kSuccess) {
     return;
   }
 
diff --git a/components/viz/service/display/overlay_strategy_single_on_top.cc b/components/viz/service/display/overlay_strategy_single_on_top.cc
index df36ded..78612ba 100644
--- a/components/viz/service/display/overlay_strategy_single_on_top.cc
+++ b/components/viz/service/display/overlay_strategy_single_on_top.cc
@@ -35,13 +35,15 @@
   QuadList* quad_list = &render_pass->quad_list;
   // Build a list of candidates with the associated quad.
   OverlayCandidate best_candidate;
+  OverlayCandidateFactory candidate_factory = OverlayCandidateFactory(
+      render_pass, resource_provider, surface_damage_rect_list,
+      &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane));
+
   auto best_quad_it = quad_list->end();
   for (auto it = quad_list->begin(); it != quad_list->end(); ++it) {
     OverlayCandidate candidate;
-    if (OverlayCandidate::FromDrawQuad(
-            resource_provider, surface_damage_rect_list, output_color_matrix,
-            *it, GetPrimaryPlaneDisplayRect(primary_plane),
-            &candidate) == OverlayCandidate::CandidateStatus::kSuccess &&
+    if (candidate_factory.FromDrawQuad(*it, candidate) ==
+            OverlayCandidate::CandidateStatus::kSuccess &&
         !candidate.has_mask_filter &&
         !OverlayCandidate::IsOccluded(candidate, quad_list->cbegin(), it)) {
       // If the candidate has been promoted previously and has not changed
@@ -92,12 +94,14 @@
   auto* render_pass = render_pass_list->back().get();
   QuadList* quad_list = &render_pass->quad_list;
   // Build a list of candidates with the associated quad.
+  OverlayCandidateFactory candidate_factory = OverlayCandidateFactory(
+      render_pass, resource_provider, surface_damage_rect_list,
+      &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane));
+
   for (auto it = quad_list->begin(); it != quad_list->end(); ++it) {
     OverlayCandidate candidate;
-    if (OverlayCandidate::FromDrawQuad(
-            resource_provider, surface_damage_rect_list, output_color_matrix,
-            *it, GetPrimaryPlaneDisplayRect(primary_plane),
-            &candidate) == OverlayCandidate::CandidateStatus::kSuccess &&
+    if (candidate_factory.FromDrawQuad(*it, candidate) ==
+            OverlayCandidate::CandidateStatus::kSuccess &&
         !candidate.has_mask_filter &&
         !OverlayCandidate::IsOccluded(candidate, quad_list->cbegin(), it)) {
       candidates->push_back({it, candidate, this});
diff --git a/components/viz/service/display/overlay_strategy_underlay.cc b/components/viz/service/display/overlay_strategy_underlay.cc
index c7aa14df..145eaff 100644
--- a/components/viz/service/display/overlay_strategy_underlay.cc
+++ b/components/viz/service/display/overlay_strategy_underlay.cc
@@ -36,13 +36,14 @@
   DCHECK(candidate_list->empty());
   auto* render_pass = render_pass_list->back().get();
   QuadList& quad_list = render_pass->quad_list;
+  auto candidate_factory = OverlayCandidateFactory(
+      render_pass, resource_provider, surface_damage_rect_list,
+      &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane));
 
   for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
     OverlayCandidate candidate;
-    if (OverlayCandidate::FromDrawQuad(
-            resource_provider, surface_damage_rect_list, output_color_matrix,
-            *it, GetPrimaryPlaneDisplayRect(primary_plane),
-            &candidate) != OverlayCandidate::CandidateStatus::kSuccess ||
+    if (candidate_factory.FromDrawQuad(*it, candidate) !=
+            OverlayCandidate::CandidateStatus::kSuccess ||
         (opaque_mode_ == OpaqueMode::RequireOpaqueCandidates &&
          !candidate.is_opaque)) {
       continue;
@@ -51,7 +52,7 @@
     // Filters read back the framebuffer to get the pixel values that need to
     // be filtered.  This is a problem when there are hardware planes because
     // the planes are not composited until they are on the display controller.
-    if (OverlayCandidate::IsOccludedByFilteredQuad(
+    if (candidate_factory.IsOccludedByFilteredQuad(
             candidate, quad_list.begin(), it, render_pass_backdrop_filters)) {
       continue;
     }
@@ -101,14 +102,14 @@
     std::vector<gfx::Rect>* content_bounds) {
   auto* render_pass = render_pass_list->back().get();
   QuadList& quad_list = render_pass->quad_list;
+  OverlayCandidateFactory candidate_factory = OverlayCandidateFactory(
+      render_pass, resource_provider, surface_damage_rect_list,
+      &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane));
 
   for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
     OverlayCandidate candidate;
-
-    if (OverlayCandidate::FromDrawQuad(
-            resource_provider, surface_damage_rect_list, output_color_matrix,
-            *it, GetPrimaryPlaneDisplayRect(primary_plane),
-            &candidate) != OverlayCandidate::CandidateStatus::kSuccess ||
+    if (candidate_factory.FromDrawQuad(*it, candidate) !=
+            OverlayCandidate::CandidateStatus::kSuccess ||
         (opaque_mode_ == OpaqueMode::RequireOpaqueCandidates &&
          !candidate.is_opaque)) {
       continue;
@@ -120,13 +121,13 @@
     // If we are requiring an overlay, then we should not block it due to this
     // condition.
     if (!candidate.requires_overlay &&
-        OverlayCandidate::IsOccludedByFilteredQuad(
+        candidate_factory.IsOccludedByFilteredQuad(
             candidate, quad_list.begin(), it, render_pass_backdrop_filters)) {
       continue;
     }
 
-    candidate.damage_area_estimate = OverlayCandidate::EstimateVisibleDamage(
-        *it, surface_damage_rect_list, quad_list.begin(), it);
+    candidate.damage_area_estimate = candidate_factory.EstimateVisibleDamage(
+        *it, candidate, quad_list.begin(), it);
 
     candidates->push_back({it, candidate, this});
   }
diff --git a/components/viz/service/display/overlay_strategy_underlay_cast.cc b/components/viz/service/display/overlay_strategy_underlay_cast.cc
index 7746bf2..d329932 100644
--- a/components/viz/service/display/overlay_strategy_underlay_cast.cc
+++ b/components/viz/service/display/overlay_strategy_underlay_cast.cc
@@ -60,6 +60,10 @@
   QuadList& quad_list = render_pass->quad_list;
   bool found_underlay = false;
   gfx::Rect content_rect;
+  OverlayCandidateFactory candidate_factory = OverlayCandidateFactory(
+      render_pass, resource_provider, surface_damage_rect_list,
+      &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane));
+
   for (const auto* quad : base::Reversed(quad_list)) {
     if (OverlayCandidate::IsInvisibleQuad(quad))
       continue;
@@ -79,12 +83,9 @@
       // quad is supposed to be to replace it with a transparent quad to allow
       // the underlay to be visible.
       // VIDEO_HOLE implies it requires overlay.
-      is_underlay =
-          quad->material == DrawQuad::Material::kVideoHole &&
-          OverlayCandidate::FromDrawQuad(
-              resource_provider, surface_damage_rect_list, output_color_matrix,
-              quad, GetPrimaryPlaneDisplayRect(primary_plane),
-              &candidate) == OverlayCandidate::CandidateStatus::kSuccess;
+      is_underlay = quad->material == DrawQuad::Material::kVideoHole &&
+                    candidate_factory.FromDrawQuad(quad, candidate) ==
+                        OverlayCandidate::CandidateStatus::kSuccess;
       found_underlay = is_underlay;
     }
 
@@ -110,10 +111,8 @@
     for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
       OverlayCandidate candidate;
       if (it->material != DrawQuad::Material::kVideoHole ||
-          OverlayCandidate::FromDrawQuad(
-              resource_provider, surface_damage_rect_list, output_color_matrix,
-              *it, GetPrimaryPlaneDisplayRect(primary_plane),
-              &candidate) != OverlayCandidate::CandidateStatus::kSuccess) {
+          candidate_factory.FromDrawQuad(*it, candidate) !=
+              OverlayCandidate::CandidateStatus::kSuccess) {
         continue;
       }
 
@@ -145,6 +144,10 @@
   QuadList& quad_list = render_pass->quad_list;
   OverlayCandidate candidate;
   auto overlay_iter = quad_list.end();
+  OverlayCandidateFactory candidate_factory = OverlayCandidateFactory(
+      render_pass, resource_provider, surface_damage_rect_list,
+      &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane));
+
   // Original code did reverse iteration.
   // Here we do forward but find the last one. which should be the same thing.
   for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
@@ -160,10 +163,8 @@
     // the underlay to be visible.
     // VIDEO_HOLE implies it requires overlay.
     if (it->material == DrawQuad::Material::kVideoHole &&
-        OverlayCandidate::FromDrawQuad(
-            resource_provider, surface_damage_rect_list, output_color_matrix,
-            *it, GetPrimaryPlaneDisplayRect(primary_plane),
-            &candidate) == OverlayCandidate::CandidateStatus::kSuccess) {
+        candidate_factory.FromDrawQuad(*it, candidate) ==
+            OverlayCandidate::CandidateStatus::kSuccess) {
       overlay_iter = it;
     }
   }
@@ -190,6 +191,10 @@
   QuadList& quad_list = render_pass->quad_list;
   bool found_underlay = false;
   gfx::Rect content_rect;
+  OverlayCandidateFactory candidate_factory = OverlayCandidateFactory(
+      render_pass, resource_provider, surface_damage_rect_list,
+      &output_color_matrix, GetPrimaryPlaneDisplayRect(primary_plane));
+
   for (const auto* quad : base::Reversed(quad_list)) {
     if (OverlayCandidate::IsInvisibleQuad(quad))
       continue;
@@ -209,12 +214,9 @@
       // quad is supposed to be to replace it with a transparent quad to allow
       // the underlay to be visible.
       // VIDEO_HOLE implies it requires overlay.
-      is_underlay =
-          quad->material == DrawQuad::Material::kVideoHole &&
-          OverlayCandidate::FromDrawQuad(
-              resource_provider, surface_damage_rect_list, output_color_matrix,
-              quad, GetPrimaryPlaneDisplayRect(primary_plane),
-              &candidate) == OverlayCandidate::CandidateStatus::kSuccess;
+      is_underlay = quad->material == DrawQuad::Material::kVideoHole &&
+                    candidate_factory.FromDrawQuad(quad, candidate) ==
+                        OverlayCandidate::CandidateStatus::kSuccess;
       found_underlay = is_underlay;
     }
 
@@ -240,10 +242,8 @@
     for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
       OverlayCandidate candidate;
       if (it->material != DrawQuad::Material::kVideoHole ||
-          OverlayCandidate::FromDrawQuad(
-              resource_provider, surface_damage_rect_list, output_color_matrix,
-              *it, GetPrimaryPlaneDisplayRect(primary_plane),
-              &candidate) != OverlayCandidate::CandidateStatus::kSuccess) {
+          candidate_factory.FromDrawQuad(*it, candidate) !=
+              OverlayCandidate::CandidateStatus::kSuccess) {
         continue;
       }
 
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc
index c7b4665..25338bd4 100644
--- a/components/viz/service/display/overlay_unittest.cc
+++ b/components/viz/service/display/overlay_unittest.cc
@@ -1190,14 +1190,13 @@
 
   // Code to make sure the 'unique' tracking ids are actually identical.
   OverlayCandidate candidate_a;
-  SkM44 ident;
-  auto ret_a = OverlayCandidate::FromDrawQuad(
-      resource_provider_.get(), &surface_damage_rect_list, ident, quad_a,
-      gfx::RectF(pass->output_rect), &candidate_a);
+  auto color_mat = GetIdentityColorMatrix();
+  auto candidate_factory = OverlayCandidateFactory(
+      pass.get(), resource_provider_.get(), &surface_damage_rect_list,
+      &color_mat, gfx::RectF(pass->output_rect));
+  auto ret_a = candidate_factory.FromDrawQuad(quad_a, candidate_a);
   OverlayCandidate candidate_b;
-  auto ret_b = OverlayCandidate::FromDrawQuad(
-      resource_provider_.get(), &surface_damage_rect_list, ident, quad_b,
-      gfx::RectF(pass->output_rect), &candidate_b);
+  auto ret_b = candidate_factory.FromDrawQuad(quad_b, candidate_b);
   EXPECT_EQ(OverlayCandidate::CandidateStatus::kSuccess, ret_a);
   EXPECT_EQ(OverlayCandidate::CandidateStatus::kSuccess, ret_b);
 
@@ -1207,10 +1206,9 @@
   pass_list.push_back(std::move(pass));
   overlay_processor_->SetFrameSequenceNumber(1);
   overlay_processor_->ProcessForOverlays(
-      resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
-      render_pass_filters, render_pass_backdrop_filters,
-      std::move(surface_damage_rect_list), nullptr, &candidate_list,
-      &damage_rect_, &content_bounds_);
+      resource_provider_.get(), &pass_list, color_mat, render_pass_filters,
+      render_pass_backdrop_filters, std::move(surface_damage_rect_list),
+      nullptr, &candidate_list, &damage_rect_, &content_bounds_);
   ASSERT_EQ(1U, candidate_list.size());
 
   // Check that one quad is gone.
@@ -1239,15 +1237,14 @@
       kCandidateRect, SurfaceId(FrameSinkId(2, 2), LocalSurfaceId()));
   // Code to make sure the 'unique' tracking ids are actually different.
   OverlayCandidate candidate_a;
-  SkM44 ident;
   SurfaceDamageRectList surface_damage_rect_list;
-  auto ret_a = OverlayCandidate::FromDrawQuad(
-      resource_provider_.get(), &surface_damage_rect_list, ident, quad_a,
-      gfx::RectF(pass->output_rect), &candidate_a);
+  auto color_mat = GetIdentityColorMatrix();
+  auto candidate_factory = OverlayCandidateFactory(
+      pass.get(), resource_provider_.get(), &surface_damage_rect_list,
+      &color_mat, gfx::RectF(pass->output_rect));
+  auto ret_a = candidate_factory.FromDrawQuad(quad_a, candidate_a);
   OverlayCandidate candidate_b;
-  auto ret_b = OverlayCandidate::FromDrawQuad(
-      resource_provider_.get(), &surface_damage_rect_list, ident, quad_b,
-      gfx::RectF(pass->output_rect), &candidate_b);
+  auto ret_b = candidate_factory.FromDrawQuad(quad_b, candidate_b);
   EXPECT_EQ(OverlayCandidate::CandidateStatus::kSuccess, ret_a);
   EXPECT_EQ(OverlayCandidate::CandidateStatus::kSuccess, ret_b);
 
@@ -4300,11 +4297,12 @@
       child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(),
       kSmallCandidateRect);
   SurfaceDamageRectList surface_damage_rect_list;
-  SkM44 default_color = GetIdentityColorMatrix();
   OverlayCandidate candidate;
-  OverlayCandidate::FromDrawQuad(resource_provider_.get(),
-                                 &surface_damage_rect_list, default_color,
-                                 new_quad, gfx::RectF(), &candidate);
+  auto color_mat = GetIdentityColorMatrix();
+  auto candidate_factory = OverlayCandidateFactory(
+      pass.get(), resource_provider_.get(), &surface_damage_rect_list,
+      &color_mat, gfx::RectF(pass->output_rect));
+  candidate_factory.FromDrawQuad(new_quad, candidate);
 
   // Verify that a default candidate is not a required overlay.
   EXPECT_FALSE(candidate.requires_overlay);
@@ -4322,11 +4320,12 @@
       kSmallCandidateRect, gfx::ProtectedVideoType::kHardwareProtected,
       YUV_420_BIPLANAR);
   SurfaceDamageRectList surface_damage_rect_list;
-  SkM44 default_color = GetIdentityColorMatrix();
   OverlayCandidate candidate;
-  OverlayCandidate::FromDrawQuad(resource_provider_.get(),
-                                 &surface_damage_rect_list, default_color,
-                                 new_quad, gfx::RectF(), &candidate);
+  auto color_mat = GetIdentityColorMatrix();
+  auto candidate_factory = OverlayCandidateFactory(
+      pass.get(), resource_provider_.get(), &surface_damage_rect_list,
+      &color_mat, gfx::RectF(pass->output_rect));
+  candidate_factory.FromDrawQuad(new_quad, candidate);
 
   // Verify that a HW protected video candidate requires overlay.
   EXPECT_TRUE(candidate.requires_overlay);
@@ -4345,11 +4344,12 @@
       YUV_420_BIPLANAR);
   pass->shared_quad_state_list.back()->clip_rect = kOverlayClipRect;
   SurfaceDamageRectList surface_damage_rect_list;
-  SkM44 default_color = GetIdentityColorMatrix();
   OverlayCandidate candidate;
-  OverlayCandidate::FromDrawQuad(resource_provider_.get(),
-                                 &surface_damage_rect_list, default_color,
-                                 new_quad, gfx::RectF(), &candidate);
+  auto color_mat = GetIdentityColorMatrix();
+  auto candidate_factory = OverlayCandidateFactory(
+      pass.get(), resource_provider_.get(), &surface_damage_rect_list,
+      &color_mat, gfx::RectF(pass->output_rect));
+  candidate_factory.FromDrawQuad(new_quad, candidate);
 
   // Default uv rect is 0.1, 0.2, 1.0, 1.0 which in the 320x240 buffer
   // corresponds to 32, 48, 288x192. That maps to |kVideoCandidateRect| in the
@@ -4378,13 +4378,14 @@
       YUV_420_BIPLANAR);
   pass->shared_quad_state_list.back()->clip_rect = kOverlayClipRect;
   SurfaceDamageRectList surface_damage_rect_list;
-  SkM44 default_color = GetIdentityColorMatrix();
   gfx::RectF primary_rect(0, 0, 100, 120);
   OverlayProcessorInterface::OutputSurfaceOverlayPlane primary_plane;
   OverlayCandidate candidate;
-  OverlayCandidate::FromDrawQuad(resource_provider_.get(),
-                                 &surface_damage_rect_list, default_color,
-                                 new_quad, primary_rect, &candidate);
+  auto color_mat = GetIdentityColorMatrix();
+  auto candidate_factory = OverlayCandidateFactory(
+      pass.get(), resource_provider_.get(), &surface_damage_rect_list,
+      &color_mat, primary_rect);
+  candidate_factory.FromDrawQuad(new_quad, candidate);
 
   // Default uv rect is 0.1, 0.2, 1.0, 1.0 which in the 320x240 buffer
   // corresponds to 32, 48, 288x192. That maps to |kVideoCandidateRect| in the
@@ -4453,7 +4454,7 @@
       kCandidateSmall * kCandidateSmall,
       kCandidateSmall * kCandidateSmall - kOccluderWidth * kOccluderWidth,
       kCandidateLarge * kCandidateLarge - kOccluderWidth * kOccluderWidth * 2,
-      kCandidateLarge * kCandidateLarge * 4 -
+      kOverlayRect.width() * kOverlayRect.height() -
           kOccluderWidth * kOccluderWidth * 2};
 
   static_assert(
@@ -4481,21 +4482,22 @@
     if (kCandidateUseSurfaceIndex[i]) {
       damaged_shared_quad_state->overlay_damage_index =
           surface_damage_rect_list.size();
-      surface_damage_rect_list.emplace_back(kCandidateRects[i]);
     } else {
       damaged_shared_quad_state->overlay_damage_index.reset();
     }
+    surface_damage_rect_list.emplace_back(kCandidateRects[i]);
 
     auto* quad_candidate = CreateCandidateQuadAt(
         resource_provider_.get(), child_resource_provider_.get(),
         child_provider_.get(), damaged_shared_quad_state, pass.get(),
         kCandidateRects[i]);
 
-    SkM44 default_color = GetIdentityColorMatrix();
     OverlayCandidate candidate;
-    OverlayCandidate::FromDrawQuad(resource_provider_.get(),
-                                   &surface_damage_rect_list, default_color,
-                                   quad_candidate, gfx::RectF(), &candidate);
+    auto color_mat = GetIdentityColorMatrix();
+    auto candidate_factory = OverlayCandidateFactory(
+        pass.get(), resource_provider_.get(), &surface_damage_rect_list,
+        &color_mat, gfx::RectF());
+    candidate_factory.FromDrawQuad(quad_candidate, candidate);
 
     // Before the 'EstimateOccludedDamage' function is called the damage area
     // will just be whatever comes from the |surface_damage_rect_list|.
@@ -4512,8 +4514,8 @@
 
     // Now we test the opaque occlusion provided by 'EstimateOccludedDamage'
     // function.
-    candidate.damage_area_estimate = OverlayCandidate::EstimateVisibleDamage(
-        quad_candidate, &surface_damage_rect_list, quad_list.begin(),
+    candidate.damage_area_estimate = candidate_factory.EstimateVisibleDamage(
+        quad_candidate, candidate, quad_list.begin(),
         std::next(quad_list.begin(), occluder_iter_count));
 
     ASSERT_EQ(kExpectedDamages[i], candidate.damage_area_estimate);
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index 8d8eec8d..932f2ce 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -1262,6 +1262,9 @@
   const DrawQuad* quad_with_overlay_damage_index = nullptr;
   if (needs_surface_damage_rect_list_ &&
       resolved_pass.aggregation().will_draw) {
+    // TODO(crbug.com/1323002): If there is one specific quad for this pass's
+    // damage we should move the allocation of the damage index below to be
+    // consistent with quad ordering.
     quad_with_overlay_damage_index =
         FindQuadWithOverlayDamage(source_pass, dest_pass, target_transform,
                                   surface, &overlay_damage_index);
diff --git a/components/webrtc/media_stream_devices_controller.cc b/components/webrtc/media_stream_devices_controller.cc
index 33ca076..95d0140 100644
--- a/components/webrtc/media_stream_devices_controller.cc
+++ b/components/webrtc/media_stream_devices_controller.cc
@@ -20,6 +20,7 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "third_party/blink/public/common/permissions/permission_utils.h"
 #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h"
 
@@ -89,7 +90,7 @@
       new MediaStreamDevicesController(web_contents, enumerator, request,
                                        std::move(callback)));
 
-  std::vector<ContentSettingsType> content_settings_types;
+  std::vector<blink::PermissionType> permission_types;
 
   permissions::PermissionManager* permission_manager =
       permissions::PermissionsClient::Get()->GetPermissionManager(
@@ -110,7 +111,7 @@
       return;
     }
 
-    content_settings_types.push_back(ContentSettingsType::MEDIASTREAM_MIC);
+    permission_types.push_back(blink::PermissionType::AUDIO_CAPTURE);
     will_prompt_for_audio =
         permission_status.content_setting == CONTENT_SETTING_ASK;
   }
@@ -127,7 +128,7 @@
       return;
     }
 
-    content_settings_types.push_back(ContentSettingsType::MEDIASTREAM_CAMERA);
+    permission_types.push_back(blink::PermissionType::VIDEO_CAPTURE);
     will_prompt_for_video =
         permission_status.content_setting == CONTENT_SETTING_ASK;
 
@@ -149,8 +150,7 @@
         return;
       }
 
-      content_settings_types.push_back(
-          ContentSettingsType::CAMERA_PAN_TILT_ZOOM);
+      permission_types.push_back(blink::PermissionType::CAMERA_PAN_TILT_ZOOM);
     }
   }
 
@@ -159,12 +159,14 @@
   // `AUDIO_CAPTURE` and `VIDEO_CAPTURE`.
   // `render_frame_host->GetMainFrame()->GetLastCommittedOrigin()` will be used
   // instead.
-  permission_manager->RequestPermissionsFromCurrentDocument(
-      content_settings_types, rfh, request.user_gesture,
-      base::BindOnce(
-          &MediaStreamDevicesController::RequestAndroidPermissionsIfNeeded,
-          web_contents, std::move(controller), will_prompt_for_audio,
-          will_prompt_for_video));
+  rfh->GetBrowserContext()
+      ->GetPermissionController()
+      ->RequestPermissionsFromCurrentDocument(
+          permission_types, rfh, request.user_gesture,
+          base::BindOnce(
+              &MediaStreamDevicesController::RequestAndroidPermissionsIfNeeded,
+              web_contents, std::move(controller), will_prompt_for_audio,
+              will_prompt_for_video));
 }
 
 MediaStreamDevicesController::~MediaStreamDevicesController() {
@@ -203,7 +205,12 @@
     std::unique_ptr<MediaStreamDevicesController> controller,
     bool did_prompt_for_audio,
     bool did_prompt_for_video,
-    const std::vector<ContentSetting>& responses) {
+    const std::vector<blink::mojom::PermissionStatus>& permissions_status) {
+  std::vector<ContentSetting> responses;
+  std::transform(permissions_status.begin(), permissions_status.end(),
+                 back_inserter(responses),
+                 permissions::PermissionUtil::PermissionStatusToContentSetting);
+
 #if BUILDFLAG(IS_ANDROID)
   // If either audio or video was previously allowed and Chrome no longer has
   // the necessary permissions, show a infobar to attempt to address this
diff --git a/components/webrtc/media_stream_devices_controller.h b/components/webrtc/media_stream_devices_controller.h
index 2a674477..61b20438 100644
--- a/components/webrtc/media_stream_devices_controller.h
+++ b/components/webrtc/media_stream_devices_controller.h
@@ -16,6 +16,7 @@
 #include "content/public/browser/media_stream_request.h"
 #include "third_party/blink/public/common/mediastream/media_stream_request.h"
 #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
+#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
 
 namespace permissions {
 enum class PermissionStatusSource;
@@ -63,7 +64,7 @@
       std::unique_ptr<MediaStreamDevicesController> controller,
       bool did_prompt_for_audio,
       bool did_prompt_for_video,
-      const std::vector<ContentSetting>& responses);
+      const std::vector<blink::mojom::PermissionStatus>& responses);
 
 #if BUILDFLAG(IS_ANDROID)
   // Called when the Android OS-level prompt is answered.
diff --git a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
index 7634f9cf..27a1f1e 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
@@ -530,7 +530,8 @@
     } else {
       child_dict->SetStringKey("error", "[Error retrieving child]");
     }
-    child_list->Append(std::move(child_dict));
+    child_list->GetList().Append(
+        base::Value::FromUniquePtrValue(std::move(child_dict)));
   }
   dict->Set(kChildrenDictAttr, std::move(child_list));
 }
diff --git a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
index 79c767d..be0c254 100644
--- a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
+++ b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
@@ -378,7 +378,7 @@
   DCHECK(routing_id != MSG_ROUTING_NONE);
   scoped_refptr<GinJavaBoundObject> object = FindObject(object_id);
   if (!object.get()) {
-    wrapped_result->Append(std::make_unique<base::Value>());
+    wrapped_result->GetList().Append(base::Value());
     *error_code = kGinJavaBridgeUnknownObjectId;
     return;
   }
@@ -404,10 +404,10 @@
                                      false,
                                      routing_id);
     }
-    wrapped_result->Append(
-        GinJavaBridgeValue::CreateObjectIDValue(returned_object_id));
+    wrapped_result->Append(base::Value::FromUniquePtrValue(
+        GinJavaBridgeValue::CreateObjectIDValue(returned_object_id)));
   } else {
-    wrapped_result->Append(std::make_unique<base::Value>());
+    wrapped_result->Append(base::Value());
   }
 }
 
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index b93ffd4..63f6db6 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -4840,8 +4840,7 @@
 
 // Verify WebUI download will success with an associated renderer process.
 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadFromWebUI) {
-  GURL webui_url(
-      GetWebUIURL("resources/images/apps/topbar_button_maximize.png"));
+  GURL webui_url(GetWebUIURL("resources/images/error.svg"));
   EXPECT_TRUE(NavigateToURL(shell(), webui_url));
   SetupEnsureNoPendingDownloads();
 
@@ -4864,7 +4863,7 @@
 // Verify WebUI download will gracefully fail without an associated renderer
 // process.
 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadFromWebUIWithoutRenderer) {
-  GURL webui_url("chrome://resources/images/apps/topbar_button_maximize.png");
+  GURL webui_url("chrome://resources/images/error.svg");
   EXPECT_TRUE(NavigateToURL(shell(), webui_url));
   SetupEnsureNoPendingDownloads();
 
diff --git a/content/browser/file_system_access/file_system_access_directory_handle_impl.cc b/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
index 964c022..7e673f9 100644
--- a/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
+++ b/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
@@ -442,10 +442,13 @@
 bool IsShellIntegratedExtension(const base::FilePath::StringType& extension) {
   base::FilePath::StringType extension_lower = base::ToLowerASCII(extension);
 
-  // .lnk files may be used to execute arbitrary code (see
-  // https://nvd.nist.gov/vuln/detail/CVE-2010-2568).
-  if (extension_lower == FILE_PATH_LITERAL("lnk"))
+  // .lnk and .scf files may be used to execute arbitrary code (see
+  // https://nvd.nist.gov/vuln/detail/CVE-2010-2568 and
+  // https://crbug.com/1227995, respectively).
+  if (extension_lower == FILE_PATH_LITERAL("lnk") ||
+      extension_lower == FILE_PATH_LITERAL("scf")) {
     return true;
+  }
 
   // Setting a file's extension to a CLSID may conceal its actual file type on
   // some Windows versions (see https://nvd.nist.gov/vuln/detail/CVE-2004-0420).
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.cc b/content/browser/file_system_access/file_system_access_manager_impl.cc
index 352b22e..0c5d648 100644
--- a/content/browser/file_system_access/file_system_access_manager_impl.cc
+++ b/content/browser/file_system_access/file_system_access_manager_impl.cc
@@ -530,6 +530,16 @@
     suggested_name_path =
         net::GenerateFileName(GURL(), std::string(), std::string(),
                               suggested_name, std::string(), std::string());
+
+    auto suggested_extension = suggested_name_path.Extension();
+    // Our version of `IsShellIntegratedExtension()` is more stringent than
+    // the version used in `net::GenerateFileName()`. See
+    // `FileSystemChooser::IsShellIntegratedExtension()` for details.
+    if (FileSystemChooser::IsShellIntegratedExtension(suggested_extension)) {
+      suggested_extension = FILE_PATH_LITERAL("download");
+      suggested_name_path =
+          suggested_name_path.ReplaceExtension(suggested_extension);
+    }
   }
 
   FileSystemChooser::Options file_system_chooser_options(
diff --git a/content/browser/file_system_access/file_system_chooser.cc b/content/browser/file_system_access/file_system_chooser.cc
index 9b8a9b7b..4adbbe5a 100644
--- a/content/browser/file_system_access/file_system_chooser.cc
+++ b/content/browser/file_system_access/file_system_chooser.cc
@@ -70,33 +70,6 @@
              : extension;
 }
 
-// Returns whether the specified extension receives special handling by the
-// Windows shell.
-bool IsShellIntegratedExtension(const base::FilePath::StringType& extension) {
-  // TODO(https://crbug.com/1154757): Figure out some way to unify this with
-  // net::IsSafePortablePathComponent, with the result probably ending up in
-  // base/i18n/file_util_icu.h.
-  base::FilePath::StringType extension_lower = base::ToLowerASCII(extension);
-
-  // .lnk files may be used to execute arbitrary code (see
-  // https://nvd.nist.gov/vuln/detail/CVE-2010-2568). .local files are used by
-  // Windows to determine which DLLs to load for an application.
-  if ((extension_lower == FILE_PATH_LITERAL("local")) ||
-      (extension_lower == FILE_PATH_LITERAL("lnk"))) {
-    return true;
-  }
-
-  // Setting a file's extension to a CLSID may conceal its actual file type on
-  // some Windows versions (see https://nvd.nist.gov/vuln/detail/CVE-2004-0420).
-  if (!extension_lower.empty() &&
-      (extension_lower.front() == FILE_PATH_LITERAL('{')) &&
-      (extension_lower.back() == FILE_PATH_LITERAL('}'))) {
-    return true;
-  }
-
-  return false;
-}
-
 // Extension validation primarily takes place in the renderer. This checks for a
 // subset of invalid extensions in the event the renderer is compromised.
 bool IsInvalidExtension(base::FilePath::StringType& extension) {
@@ -104,7 +77,7 @@
   auto extension16 = base::UTF8ToUTF16(component8);
 
   return !base::i18n::IsFilenameLegal(extension16) ||
-         IsShellIntegratedExtension(GetLastExtension(extension));
+         FileSystemChooser::IsShellIntegratedExtension(extension);
 }
 
 // Converts the accepted mime types and extensions from `option` into a list
@@ -289,6 +262,40 @@
       /*params=*/nullptr);
 }
 
+// static
+bool FileSystemChooser::IsShellIntegratedExtension(
+    const base::FilePath::StringType& extension) {
+  // TODO(https://crbug.com/1154757): Figure out some way to unify this with
+  // net::IsSafePortablePathComponent, with the result probably ending up in
+  // base/i18n/file_util_icu.h.
+  // - For the sake of consistency across platforms, we sanitize '.lnk' and
+  //   '.local' files on all platforms (not just Windows)
+  // - There are some extensions (i.e. '.scf') we would like to sanitize which
+  //   `net::GenerateFileName()` does not
+  base::FilePath::StringType extension_lower =
+      base::ToLowerASCII(GetLastExtension(extension));
+
+  // .lnk and .scf files may be used to execute arbitrary code (see
+  // https://nvd.nist.gov/vuln/detail/CVE-2010-2568 and
+  // https://crbug.com/1227995, respectively). .local files are used by Windows
+  // to determine which DLLs to load for an application.
+  if ((extension_lower == FILE_PATH_LITERAL("lnk")) ||
+      (extension_lower == FILE_PATH_LITERAL("local")) ||
+      (extension_lower == FILE_PATH_LITERAL("scf"))) {
+    return true;
+  }
+
+  // Setting a file's extension to a CLSID may conceal its actual file type on
+  // some Windows versions (see https://nvd.nist.gov/vuln/detail/CVE-2004-0420).
+  if (!extension_lower.empty() &&
+      (extension_lower.front() == FILE_PATH_LITERAL('{')) &&
+      (extension_lower.back() == FILE_PATH_LITERAL('}'))) {
+    return true;
+  }
+
+  return false;
+}
+
 FileSystemChooser::FileSystemChooser(ui::SelectFileDialog::Type type,
                                      ResultCallback callback,
                                      base::ScopedClosureRunner fullscreen_block)
diff --git a/content/browser/file_system_access/file_system_chooser.h b/content/browser/file_system_access/file_system_chooser.h
index a2d1e435..113af84 100644
--- a/content/browser/file_system_access/file_system_chooser.h
+++ b/content/browser/file_system_access/file_system_chooser.h
@@ -69,6 +69,12 @@
                             ResultCallback callback,
                             base::ScopedClosureRunner fullscreen_block);
 
+  // Returns whether the specified extension receives special handling by the
+  // Windows shell. These extensions should be sanitized before being shown in
+  // the "save as" file picker.
+  static bool IsShellIntegratedExtension(
+      const base::FilePath::StringType& extension);
+
   FileSystemChooser(ui::SelectFileDialog::Type type,
                     ResultCallback callback,
                     base::ScopedClosureRunner fullscreen_block);
diff --git a/content/browser/file_system_access/file_system_chooser_browsertest.cc b/content/browser/file_system_access/file_system_chooser_browsertest.cc
index dc310d0..9ea4db7 100644
--- a/content/browser/file_system_access/file_system_chooser_browsertest.cc
+++ b/content/browser/file_system_access/file_system_chooser_browsertest.cc
@@ -1556,22 +1556,28 @@
   name_infos.push_back({"not_matching.jpg", ListValueOf(".txt"), false,
                         "not_matching.jpg", false});
 
-#if BUILDFLAG(IS_WIN)
-  // ".local" and ".lnk" extensions should be sanitized on Windows.
+  // ".lnk", ".local", and ".scf" extensions should be sanitized.
   name_infos.push_back({"dangerous_extension.local", ListValueOf(".local"),
                         true, "dangerous_extension.download", false});
   name_infos.push_back({"dangerous_extension.lnk", ListValueOf(".lnk"), true,
                         "dangerous_extension.download", false});
-#else
-  // ".local" and ".lnk" extensions should be allowed on other OSes.
-  // TODO(https://crbug.com/1154757): `expected_exclude_accept_all_option` is
-  // false here because ".local" and ".lnk" extensions are not allowed in
-  // `accepts`, but are only sanitized by net::GenerateSafeFileName on Windows.
-  name_infos.push_back({"dangerous_extension.local", ListValueOf(".local"),
-                        true, "dangerous_extension.local", false});
-  name_infos.push_back({"dangerous_extension.lnk", ListValueOf(".lnk"), true,
-                        "dangerous_extension.lnk", false});
-#endif
+  name_infos.push_back({"dangerous_extension.scf", ListValueOf(".scf"), true,
+                        "dangerous_extension.download", false});
+  // Compound extensions ending in a dangerous extension should be sanitized.
+  name_infos.push_back({"dangerous_extension.png.local", ListValueOf(".local"),
+                        true, "dangerous_extension.png.download", false});
+  name_infos.push_back({"dangerous_extension.png.lnk", ListValueOf(".lnk"),
+                        true, "dangerous_extension.png.download", false});
+  name_infos.push_back({"dangerous_extension.png.scf", ListValueOf(".scf"),
+                        true, "dangerous_extension.png.download", false});
+  // Compound extensions not ending in a dangerous extension should not be
+  // sanitized.
+  name_infos.push_back({"dangerous_extension.local.png", ListValueOf(".png"),
+                        true, "dangerous_extension.local.png", true});
+  name_infos.push_back({"dangerous_extension.lnk.png", ListValueOf(".png"),
+                        true, "dangerous_extension.lnk.png", true});
+  name_infos.push_back({"dangerous_extension.scf.png", ListValueOf(".png"),
+                        true, "dangerous_extension.scf.png", true});
   // Invalid characters should be sanitized.
   name_infos.push_back({R"(inv*l:d\\ch%rבאמת!a<ters🤓.txt)",
                         ListValueOf(".txt"), true,
diff --git a/content/browser/file_system_access/file_system_chooser_unittest.cc b/content/browser/file_system_access/file_system_chooser_unittest.cc
index 373de41..9b27d63 100644
--- a/content/browser/file_system_access/file_system_chooser_unittest.cc
+++ b/content/browser/file_system_access/file_system_chooser_unittest.cc
@@ -189,7 +189,7 @@
   accepts.emplace_back(blink::mojom::ChooseFileSystemEntryAcceptsOption::New(
       u"", std::vector<std::string>({}),
       std::vector<std::string>(
-          {"lnk", "foo.lnk", "foo.bar.local", "text", "local"})));
+          {"lnk", "foo.lnk", "foo.bar.local", "text", "local", "scf"})));
   SyncShowDialog(std::move(accepts), /*include_accepts_all=*/false);
 
   ASSERT_TRUE(dialog_params.file_types);
diff --git a/content/browser/font_access/font_access_manager_unittest.cc b/content/browser/font_access/font_access_manager_unittest.cc
index d73a147..ac90756 100644
--- a/content/browser/font_access/font_access_manager_unittest.cc
+++ b/content/browser/font_access/font_access_manager_unittest.cc
@@ -19,7 +19,6 @@
 #include "content/browser/font_access/font_access_test_utils.h"
 #include "content/browser/font_access/font_enumeration_cache.h"
 #include "content/browser/font_access/font_enumeration_data_source.h"
-#include "content/browser/permissions/permission_controller_impl.h"
 #include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/public/test/test_browser_context.h"
@@ -103,8 +102,6 @@
         static_cast<TestBrowserContext*>(main_rfh()->GetBrowserContext());
     browser_context->SetPermissionControllerDelegate(
         std::make_unique<TestFontAccessPermissionManager>());
-    permission_controller_ =
-        std::make_unique<PermissionControllerImpl>(browser_context);
   }
 
   void TearDown() override {
@@ -128,37 +125,37 @@
   void AutoGrantPermission() {
     test_permission_manager()->SetRequestCallback(base::BindRepeating(
         [](TestFontAccessPermissionManager::PermissionCallback callback) {
-          std::move(callback).Run(blink::mojom::PermissionStatus::GRANTED);
+          std::move(callback).Run({blink::mojom::PermissionStatus::GRANTED});
         }));
-    test_permission_manager()->SetPermissionStatusForFrame(
+    test_permission_manager()->SetPermissionStatusForCurrentDocument(
         blink::mojom::PermissionStatus::GRANTED);
   }
 
   void AutoDenyPermission() {
     test_permission_manager()->SetRequestCallback(base::BindRepeating(
         [](TestFontAccessPermissionManager::PermissionCallback callback) {
-          std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
+          std::move(callback).Run({blink::mojom::PermissionStatus::DENIED});
         }));
-    test_permission_manager()->SetPermissionStatusForFrame(
+    test_permission_manager()->SetPermissionStatusForCurrentDocument(
         blink::mojom::PermissionStatus::DENIED);
   }
 
   void AskGrantPermission() {
-    test_permission_manager()->SetPermissionStatusForFrame(
-        blink::mojom::PermissionStatus::ASK);
     test_permission_manager()->SetRequestCallback(base::BindRepeating(
         [](TestFontAccessPermissionManager::PermissionCallback callback) {
-          std::move(callback).Run(blink::mojom::PermissionStatus::GRANTED);
+          std::move(callback).Run({blink::mojom::PermissionStatus::GRANTED});
         }));
+    test_permission_manager()->SetPermissionStatusForCurrentDocument(
+        blink::mojom::PermissionStatus::ASK);
   }
 
   void AskDenyPermission() {
-    test_permission_manager()->SetPermissionStatusForFrame(
-        blink::mojom::PermissionStatus::ASK);
     test_permission_manager()->SetRequestCallback(base::BindRepeating(
         [](TestFontAccessPermissionManager::PermissionCallback callback) {
-          std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
+          std::move(callback).Run({blink::mojom::PermissionStatus::DENIED});
         }));
+    test_permission_manager()->SetPermissionStatusForCurrentDocument(
+        blink::mojom::PermissionStatus::ASK);
   }
 
   void SetFrameHidden() { test_rvh()->SimulateWasHidden(); }
@@ -169,7 +166,6 @@
   const GURL kTestUrl = GURL("https://example.com/font_access");
   const url::Origin kTestOrigin = url::Origin::Create(GURL(kTestUrl));
 
-  std::unique_ptr<PermissionControllerImpl> permission_controller_;
   std::unique_ptr<FontAccessManager> manager_;
   mojo::Remote<blink::mojom::FontAccessManager> manager_remote_;
   std::unique_ptr<FontAccessManagerSync> manager_sync_;
@@ -289,4 +285,4 @@
 
 }  // namespace
 
-}  // namespace content
\ No newline at end of file
+}  // namespace content
diff --git a/content/browser/font_access/font_access_test_utils.cc b/content/browser/font_access/font_access_test_utils.cc
index 0ba7467c..2a2dae9 100644
--- a/content/browser/font_access/font_access_test_utils.cc
+++ b/content/browser/font_access/font_access_test_utils.cc
@@ -11,30 +11,22 @@
 TestFontAccessPermissionManager::TestFontAccessPermissionManager() = default;
 TestFontAccessPermissionManager::~TestFontAccessPermissionManager() = default;
 
-void TestFontAccessPermissionManager::RequestPermission(
-    blink::PermissionType permissions,
-    RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin,
+void TestFontAccessPermissionManager::RequestPermissionsFromCurrentDocument(
+    const std::vector<blink::PermissionType>& permissions,
+    content::RenderFrameHost* render_frame_host,
     bool user_gesture,
-    PermissionCallback callback) {
-  EXPECT_EQ(permissions, blink::PermissionType::LOCAL_FONTS);
+    base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
+        callback) {
+  EXPECT_EQ(permissions[0], blink::PermissionType::LOCAL_FONTS);
   EXPECT_TRUE(user_gesture);
   request_callback_.Run(std::move(callback));
 }
 
 blink::mojom::PermissionStatus
-TestFontAccessPermissionManager::GetPermissionStatusForFrame(
-    blink::PermissionType permission,
-    RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin) {
-  return permission_status_for_frame_;
-}
-
-blink::mojom::PermissionStatus
 TestFontAccessPermissionManager::GetPermissionStatusForCurrentDocument(
     blink::PermissionType permission,
     RenderFrameHost* render_frame_host) {
-  return permission_status_for_frame_;
+  return permission_status_for_current_document_;
 }
 
 }  // namespace content
diff --git a/content/browser/font_access/font_access_test_utils.h b/content/browser/font_access/font_access_test_utils.h
index 8bf7a15ce..75b0d506 100644
--- a/content/browser/font_access/font_access_test_utils.h
+++ b/content/browser/font_access/font_access_test_utils.h
@@ -24,19 +24,16 @@
 
   ~TestFontAccessPermissionManager() override;
 
-  using PermissionCallback =
-      base::OnceCallback<void(blink::mojom::PermissionStatus)>;
+  using PermissionCallback = base::OnceCallback<void(
+      const std::vector<blink::mojom::PermissionStatus>&)>;
 
-  void RequestPermission(blink::PermissionType permissions,
-                         RenderFrameHost* render_frame_host,
-                         const GURL& requesting_origin,
-                         bool user_gesture,
-                         PermissionCallback callback) override;
-
-  blink::mojom::PermissionStatus GetPermissionStatusForFrame(
-      blink::PermissionType permission,
-      RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin) override;
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<
+          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+      override;
 
   blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
       blink::PermissionType permission,
@@ -47,13 +44,14 @@
     request_callback_ = std::move(request_callback);
   }
 
-  void SetPermissionStatusForFrame(blink::mojom::PermissionStatus status) {
-    permission_status_for_frame_ = status;
+  void SetPermissionStatusForCurrentDocument(
+      blink::mojom::PermissionStatus status) {
+    permission_status_for_current_document_ = status;
   }
 
  private:
   base::RepeatingCallback<void(PermissionCallback)> request_callback_;
-  blink::mojom::PermissionStatus permission_status_for_frame_ =
+  blink::mojom::PermissionStatus permission_status_for_current_document_ =
       blink::mojom::PermissionStatus::ASK;
 };
 
diff --git a/content/browser/generic_sensor/sensor_provider_proxy_impl_unittest.cc b/content/browser/generic_sensor/sensor_provider_proxy_impl_unittest.cc
index 5c830ea..f826e54 100644
--- a/content/browser/generic_sensor/sensor_provider_proxy_impl_unittest.cc
+++ b/content/browser/generic_sensor/sensor_provider_proxy_impl_unittest.cc
@@ -26,15 +26,16 @@
 // grants blink::PermissionType::SENSORS requests.
 class TestPermissionManager : public MockPermissionManager {
  public:
-  void RequestPermission(
-      blink::PermissionType permission,
-      RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin,
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      content::RenderFrameHost* render_frame_host,
       bool user_gesture,
-      base::OnceCallback<void(blink::mojom::PermissionStatus)> callback)
+      base::OnceCallback<
+          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
       override {
-    ASSERT_EQ(permission, blink::PermissionType::SENSORS);
-    std::move(callback).Run(blink::mojom::PermissionStatus::GRANTED);
+    ASSERT_EQ(permissions.size(), 1ul);
+    ASSERT_EQ(permissions[0], blink::PermissionType::SENSORS);
+    std::move(callback).Run({blink::mojom::PermissionStatus::GRANTED});
   }
 };
 
diff --git a/content/browser/geolocation/geolocation_service_impl_unittest.cc b/content/browser/geolocation/geolocation_service_impl_unittest.cc
index 1dd28f3..93ca8d3 100644
--- a/content/browser/geolocation/geolocation_service_impl_unittest.cc
+++ b/content/browser/geolocation/geolocation_service_impl_unittest.cc
@@ -33,7 +33,8 @@
 namespace content {
 namespace {
 
-using PermissionCallback = base::OnceCallback<void(PermissionStatus)>;
+using PermissionCallback = base::OnceCallback<void(
+    const std::vector<blink::mojom::PermissionStatus>&)>;
 
 double kMockLatitude = 1.0;
 double kMockLongitude = 10.0;
@@ -43,12 +44,15 @@
   TestPermissionManager() = default;
   ~TestPermissionManager() override = default;
 
-  void RequestPermission(blink::PermissionType permissions,
-                         RenderFrameHost* render_frame_host,
-                         const GURL& requesting_origin,
-                         bool user_gesture,
-                         PermissionCallback callback) override {
-    EXPECT_EQ(permissions, blink::PermissionType::GEOLOCATION);
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<
+          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+      override {
+    ASSERT_EQ(permissions.size(), 1u);
+    EXPECT_EQ(permissions[0], blink::PermissionType::GEOLOCATION);
     EXPECT_TRUE(user_gesture);
     request_callback_.Run(std::move(callback));
   }
@@ -173,7 +177,7 @@
 
   permission_manager()->SetRequestCallback(
       base::BindRepeating([](PermissionCallback callback) {
-        std::move(callback).Run(PermissionStatus::GRANTED);
+        std::move(callback).Run(std::vector{PermissionStatus::GRANTED});
       }));
   mojo::Remote<Geolocation> geolocation;
   service_remote()->CreateGeolocation(
@@ -201,7 +205,7 @@
       /*allow_via_permissions_policy=*/true);
   permission_manager()->SetRequestCallback(
       base::BindRepeating([](PermissionCallback callback) {
-        std::move(callback).Run(PermissionStatus::GRANTED);
+        std::move(callback).Run(std::vector{PermissionStatus::GRANTED});
       }));
   mojo::Remote<Geolocation> geolocation;
   service_remote()->CreateGeolocation(
@@ -229,7 +233,7 @@
       /*allow_via_permissions_policy=*/true);
   permission_manager()->SetRequestCallback(
       base::BindRepeating([](PermissionCallback callback) {
-        std::move(callback).Run(PermissionStatus::DENIED);
+        std::move(callback).Run(std::vector{PermissionStatus::DENIED});
       }));
   mojo::Remote<Geolocation> geolocation;
   service_remote()->CreateGeolocation(
@@ -254,7 +258,7 @@
       base::BindRepeating([](PermissionCallback permission_callback) {
         base::ThreadTaskRunnerHandle::Get()->PostTask(
             FROM_HERE, base::BindOnce(std::move(permission_callback),
-                                      PermissionStatus::GRANTED));
+                                      std::vector{PermissionStatus::GRANTED}));
       }));
   mojo::Remote<Geolocation> geolocation;
   service_remote()->CreateGeolocation(
@@ -284,7 +288,7 @@
       base::BindRepeating([](PermissionCallback permission_callback) {
         base::ThreadTaskRunnerHandle::Get()->PostTask(
             FROM_HERE, base::BindOnce(std::move(permission_callback),
-                                      PermissionStatus::DENIED));
+                                      std::vector{PermissionStatus::DENIED}));
       }));
   mojo::Remote<Geolocation> geolocation;
   service_remote()->CreateGeolocation(
diff --git a/content/browser/interest_group/ad_auction_service_impl_unittest.cc b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
index d52401be..264827c 100644
--- a/content/browser/interest_group/ad_auction_service_impl_unittest.cc
+++ b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
@@ -4014,9 +4014,9 @@
 }
 
 // When sending reports, the next report request is feteched after the previous
-// report request completed (either succeeded or failed). Reporting should
-// continue even after the page navigated away. Timeout works for report
-// requests.
+// report request completed (`max_active_report_requests_` is set to 1 in this
+// test). Reporting should continue even after the page navigated away. Timeout
+// works for report requests.
 TEST_F(AdAuctionServiceImplTest, SendReports) {
   const std::string kBiddingScript = base::StringPrintf(R"(
 function generateBid(
@@ -4049,6 +4049,7 @@
                          kOriginStringA, kOriginStringA);
 
   manager_->set_reporting_interval_for_testing(base::Seconds(5));
+  manager_->set_max_active_report_requests_for_testing(1);
   network_responder_->RegisterScriptResponse(kBiddingUrlPath, kBiddingScript);
   network_responder_->RegisterScriptResponse(kDecisionUrlPath, kDecisionScript);
   network_responder_->RegisterReportResponse("/report_bidder", /*response=*/"");
@@ -4133,6 +4134,7 @@
                          kOriginStringA, kOriginStringA);
 
   manager_->set_reporting_interval_for_testing(base::Seconds(5));
+  manager_->set_max_active_report_requests_for_testing(1);
   network_responder_->RegisterScriptResponse(kBiddingUrlPath, kBiddingScript);
   network_responder_->RegisterScriptResponse(kDecisionUrlPath, kDecisionScript);
   network_responder_->RegisterReportResponse("/report_bidder", /*response=*/"");
@@ -4213,6 +4215,7 @@
                          kOriginStringA, kOriginStringA);
 
   manager_->set_max_report_queue_length_for_testing(1);
+  manager_->set_max_active_report_requests_for_testing(1);
   manager_->set_reporting_interval_for_testing(base::Seconds(5));
   network_responder_->RegisterScriptResponse(kBiddingUrlPath, kBiddingScript);
   network_responder_->RegisterScriptResponse(kDecisionUrlPath, kDecisionScript);
@@ -4704,6 +4707,136 @@
       "Ads.InterestGroup.Auction.NumAuctionsSkippedDueToAuctionLimit", 0, 1);
 }
 
+// CreateAdRequest should reject if we have an empty config.
+TEST_F(AdAuctionServiceImplTest, CreateAdRequestRejectsEmptyConfigRequest) {
+  auto mojo_config = blink::mojom::AdRequestConfig::New();
+  bool callback_fired = false;
+  CreateAdRequest(std::move(mojo_config),
+                  base::BindLambdaForTesting(
+                      [&](const absl::optional<std::string>& ads_guid) {
+                        ASSERT_FALSE(ads_guid.has_value());
+                        callback_fired = true;
+                      }));
+  ASSERT_TRUE(callback_fired);
+}
+
+// CreateAdRequest should reject if we have an otherwise okay request but our
+// request URL is not using HTTPS.
+TEST_F(AdAuctionServiceImplTest, CreateAdRequestRejectsHttpUrls) {
+  auto mojo_config = blink::mojom::AdRequestConfig::New();
+  mojo_config->ad_request_url = GURL("http://site.test/");
+  auto mojo_ad_properties = blink::mojom::AdProperties::New();
+  mojo_ad_properties->width = "48";
+  mojo_ad_properties->height = "64";
+  mojo_ad_properties->slot = "123";
+  mojo_ad_properties->lang = "en";
+  mojo_ad_properties->ad_type = "test";
+  mojo_ad_properties->bid_floor = 1.0;
+  mojo_config->ad_properties.push_back(std::move(mojo_ad_properties));
+
+  bool callback_fired = false;
+  CreateAdRequest(std::move(mojo_config),
+                  base::BindLambdaForTesting(
+                      [&](const absl::optional<std::string>& ads_guid) {
+                        ASSERT_FALSE(ads_guid.has_value());
+                        callback_fired = true;
+                      }));
+  ASSERT_TRUE(callback_fired);
+}
+
+// CreateAdRequest should reject if we have an otherwise okay request but no ad
+// properties.
+TEST_F(AdAuctionServiceImplTest, CreateAdRequestRejectsMissingAds) {
+  auto mojo_config = blink::mojom::AdRequestConfig::New();
+  mojo_config->ad_request_url = GURL("https://site.test/");
+
+  bool callback_fired = false;
+  CreateAdRequest(std::move(mojo_config),
+                  base::BindLambdaForTesting(
+                      [&](const absl::optional<std::string>& ads_guid) {
+                        ASSERT_FALSE(ads_guid.has_value());
+                        callback_fired = true;
+                      }));
+  ASSERT_TRUE(callback_fired);
+}
+
+// CreateAdRequest should reject if we have an otherwise okay request but
+// include an HTTP fallback URL.
+TEST_F(AdAuctionServiceImplTest, CreateAdRequestRejectsHttpFallback) {
+  auto mojo_config = blink::mojom::AdRequestConfig::New();
+  mojo_config->ad_request_url = GURL("https://site.test/");
+  auto mojo_ad_properties = blink::mojom::AdProperties::New();
+  mojo_ad_properties->width = "48";
+  mojo_ad_properties->height = "64";
+  mojo_ad_properties->slot = "123";
+  mojo_ad_properties->lang = "en";
+  mojo_ad_properties->ad_type = "test";
+  mojo_ad_properties->bid_floor = 1.0;
+  mojo_config->ad_properties.push_back(std::move(mojo_ad_properties));
+
+  mojo_config->fallback_source = GURL("http://fallback_site.test/");
+
+  bool callback_fired = false;
+  CreateAdRequest(std::move(mojo_config),
+                  base::BindLambdaForTesting(
+                      [&](const absl::optional<std::string>& ads_guid) {
+                        ASSERT_FALSE(ads_guid.has_value());
+                        callback_fired = true;
+                      }));
+  ASSERT_TRUE(callback_fired);
+}
+
+// An empty config will cause FinalizeAd to fail and run the supplied callback.
+TEST_F(AdAuctionServiceImplTest, FinalizeAdRejectsEmptyConfig) {
+  auto mojo_config = blink::mojom::AuctionAdConfig::New();
+  mojo_config->auction_ad_config_non_shared_params =
+      blink::mojom::AuctionAdConfigNonSharedParams::New();
+
+  bool callback_fired = false;
+  FinalizeAd(
+      /*guid=*/std::string("1234"), std::move(mojo_config),
+      base::BindLambdaForTesting([&](const absl::optional<GURL>& creative_url) {
+        ASSERT_FALSE(creative_url.has_value());
+        callback_fired = true;
+      }));
+  ASSERT_TRUE(callback_fired);
+}
+
+TEST_F(AdAuctionServiceImplTest, FinalizeAdRejectsHTTPDecisionUrl) {
+  auto mojo_config = blink::mojom::AuctionAdConfig::New();
+  mojo_config->auction_ad_config_non_shared_params =
+      blink::mojom::AuctionAdConfigNonSharedParams::New();
+  mojo_config->seller = url::Origin::Create(GURL("https://site.test"));
+  mojo_config->decision_logic_url = GURL("http://site.test/");
+
+  bool callback_fired = false;
+  FinalizeAd(
+      /*guid=*/"1234", std::move(mojo_config),
+      base::BindLambdaForTesting([&](const absl::optional<GURL>& creative_url) {
+        ASSERT_FALSE(creative_url.has_value());
+        callback_fired = true;
+      }));
+  ASSERT_TRUE(callback_fired);
+}
+
+// An empty GUID should trigger any FinalizeAd request to fail.
+TEST_F(AdAuctionServiceImplTest, FinalizeAdRejectsMissingGuid) {
+  auto mojo_config = blink::mojom::AuctionAdConfig::New();
+  mojo_config->auction_ad_config_non_shared_params =
+      blink::mojom::AuctionAdConfigNonSharedParams::New();
+  mojo_config->seller = url::Origin::Create(GURL("https://site.test"));
+  mojo_config->decision_logic_url = GURL("https://site.test/");
+
+  bool callback_fired = false;
+  FinalizeAd(
+      /*guid=*/std::string(), std::move(mojo_config),
+      base::BindLambdaForTesting([&](const absl::optional<GURL>& creative_url) {
+        ASSERT_FALSE(creative_url.has_value());
+        callback_fired = true;
+      }));
+  ASSERT_TRUE(callback_fired);
+}
+
 class AdAuctionServiceImplNumAuctionLimitTest
     : public AdAuctionServiceImplTest {
  public:
@@ -5068,134 +5201,126 @@
   EXPECT_EQ(1, GetJoinCount(kOriginC, kInterestGroupName));
 }
 
-// CreateAdRequest should reject if we have an empty config.
-TEST_F(AdAuctionServiceImplTest, CreateAdRequestRejectsEmptyConfigRequest) {
-  auto mojo_config = blink::mojom::AdRequestConfig::New();
-  bool callback_fired = false;
-  CreateAdRequest(std::move(mojo_config),
-                  base::BindLambdaForTesting(
-                      [&](const absl::optional<std::string>& ads_guid) {
-                        ASSERT_FALSE(ads_guid.has_value());
-                        callback_fired = true;
-                      }));
-  ASSERT_TRUE(callback_fired);
+class AdAuctionServiceImplBiddingAndScoringDebugReportingAPIEnabledTest
+    : public AdAuctionServiceImplTest {
+ public:
+  AdAuctionServiceImplBiddingAndScoringDebugReportingAPIEnabledTest() {
+    feature_list_.InitAndEnableFeature(
+        blink::features::kBiddingAndScoringDebugReportingAPI);
+  }
+
+ protected:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// Allowing sending multiple reports in parallel, instead of only allowing
+// sending one at a time.
+TEST_F(AdAuctionServiceImplBiddingAndScoringDebugReportingAPIEnabledTest,
+       SendReportsMaxiumActive) {
+  // Use interest group name as bid value.
+  const std::string kBiddingScript =
+      base::StringPrintf(R"(
+function generateBid(
+    interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals,
+    browserSignals) {
+  forDebuggingOnly.reportAdAuctionWin(
+      `%s/bidder_debug_win_` + interestGroup.name);
+  return {
+    'ad': 'example',
+    'bid': parseInt(interestGroup.name),
+    'render': 'https://example.com/render'
+  };
 }
-
-// CreateAdRequest should reject if we have an otherwise okay request but our
-// request URL is not using HTTPS.
-TEST_F(AdAuctionServiceImplTest, CreateAdRequestRejectsHttpUrls) {
-  auto mojo_config = blink::mojom::AdRequestConfig::New();
-  mojo_config->ad_request_url = GURL("http://site.test/");
-  auto mojo_ad_properties = blink::mojom::AdProperties::New();
-  mojo_ad_properties->width = "48";
-  mojo_ad_properties->height = "64";
-  mojo_ad_properties->slot = "123";
-  mojo_ad_properties->lang = "en";
-  mojo_ad_properties->ad_type = "test";
-  mojo_ad_properties->bid_floor = 1.0;
-  mojo_config->ad_properties.push_back(std::move(mojo_ad_properties));
-
-  bool callback_fired = false;
-  CreateAdRequest(std::move(mojo_config),
-                  base::BindLambdaForTesting(
-                      [&](const absl::optional<std::string>& ads_guid) {
-                        ASSERT_FALSE(ads_guid.has_value());
-                        callback_fired = true;
-                      }));
-  ASSERT_TRUE(callback_fired);
+function reportWin(
+    auctionSignals, perBuyerSignals, sellerSignals, browserSignals) {
+  sendReportTo('%s/report_bidder_' + browserSignals.bid);
 }
+  )",
+                         kOriginStringA, kOriginStringA);
 
-// CreateAdRequest should reject if we have an otherwise okay request but no ad
-// properties.
-TEST_F(AdAuctionServiceImplTest, CreateAdRequestRejectsMissingAds) {
-  auto mojo_config = blink::mojom::AdRequestConfig::New();
-  mojo_config->ad_request_url = GURL("https://site.test/");
-
-  bool callback_fired = false;
-  CreateAdRequest(std::move(mojo_config),
-                  base::BindLambdaForTesting(
-                      [&](const absl::optional<std::string>& ads_guid) {
-                        ASSERT_FALSE(ads_guid.has_value());
-                        callback_fired = true;
-                      }));
-  ASSERT_TRUE(callback_fired);
+  const std::string kDecisionScript =
+      base::StringPrintf(R"(
+function scoreAd(
+    adMetadata, bid, auctionConfig, trustedScoringSignals, browserSignals) {
+  forDebuggingOnly.reportAdAuctionWin(`%s/seller_debug_win_` + bid);
+  return bid;
 }
-
-// CreateAdRequest should reject if we have an otherwise okay request but
-// include an HTTP fallback URL.
-TEST_F(AdAuctionServiceImplTest, CreateAdRequestRejectsHttpFallback) {
-  auto mojo_config = blink::mojom::AdRequestConfig::New();
-  mojo_config->ad_request_url = GURL("https://site.test/");
-  auto mojo_ad_properties = blink::mojom::AdProperties::New();
-  mojo_ad_properties->width = "48";
-  mojo_ad_properties->height = "64";
-  mojo_ad_properties->slot = "123";
-  mojo_ad_properties->lang = "en";
-  mojo_ad_properties->ad_type = "test";
-  mojo_ad_properties->bid_floor = 1.0;
-  mojo_config->ad_properties.push_back(std::move(mojo_ad_properties));
-
-  mojo_config->fallback_source = GURL("http://fallback_site.test/");
-
-  bool callback_fired = false;
-  CreateAdRequest(std::move(mojo_config),
-                  base::BindLambdaForTesting(
-                      [&](const absl::optional<std::string>& ads_guid) {
-                        ASSERT_FALSE(ads_guid.has_value());
-                        callback_fired = true;
-                      }));
-  ASSERT_TRUE(callback_fired);
+function reportResult(auctionConfig, browserSignals) {
+  const reportUrl = '%s/report_seller_' + browserSignals.bid;
+  sendReportTo(reportUrl);
+  return {
+    'success': true,
+    'signalsForWinner': {'signalForWinner': 1},
+    'reportUrl': reportUrl,
+  };
 }
+)",
+                         kOriginStringA, kOriginStringA);
 
-// An empty config will cause FinalizeAd to fail and run the supplied callback.
-TEST_F(AdAuctionServiceImplTest, FinalizeAdRejectsEmptyConfig) {
-  auto mojo_config = blink::mojom::AuctionAdConfig::New();
-  mojo_config->auction_ad_config_non_shared_params =
-      blink::mojom::AuctionAdConfigNonSharedParams::New();
+  manager_->set_max_report_queue_length_for_testing(50);
+  manager_->set_max_active_report_requests_for_testing(3);
+  manager_->set_reporting_interval_for_testing(base::Seconds(5));
+  network_responder_->RegisterScriptResponse(kBiddingUrlPath, kBiddingScript);
+  network_responder_->RegisterScriptResponse(kDecisionUrlPath, kDecisionScript);
 
-  bool callback_fired = false;
-  FinalizeAd(
-      /*guid=*/std::string("1234"), std::move(mojo_config),
-      base::BindLambdaForTesting([&](const absl::optional<GURL>& creative_url) {
-        ASSERT_FALSE(creative_url.has_value());
-        callback_fired = true;
-      }));
-  ASSERT_TRUE(callback_fired);
-}
+  // Run two auctions, each time with a new interest group which bids i wins
+  // the auction.
+  for (int i = 1; i < 3; i++) {
+    const std::string name = base::NumberToString(i);
+    network_responder_->RegisterReportResponse(
+        base::StringPrintf("/report_bidder_%s", name.c_str()), "");
+    network_responder_->RegisterReportResponse(
+        base::StringPrintf("/report_seller_%s", name.c_str()), "");
+    network_responder_->RegisterReportResponse(
+        base::StringPrintf("/seller_debug_win_%s", name.c_str()), "");
+    network_responder_->RegisterReportResponse(
+        base::StringPrintf("/bidder_debug_win_%s", name.c_str()), "");
+    blink::InterestGroup interest_group = CreateInterestGroup();
+    interest_group.bidding_url = kUrlA.Resolve(kBiddingUrlPath);
+    interest_group.name = name;
+    interest_group.ads.emplace();
+    blink::InterestGroup::Ad ad(
+        /*render_url=*/GURL("https://example.com/render"),
+        /*metadata=*/absl::nullopt);
+    interest_group.ads->emplace_back(std::move(ad));
+    JoinInterestGroupAndFlush(interest_group);
+    EXPECT_EQ(1, GetJoinCount(kOriginA, name));
 
-TEST_F(AdAuctionServiceImplTest, FinalizeAdRejectsHTTPDecisionUrl) {
-  auto mojo_config = blink::mojom::AuctionAdConfig::New();
-  mojo_config->auction_ad_config_non_shared_params =
-      blink::mojom::AuctionAdConfigNonSharedParams::New();
-  mojo_config->seller = url::Origin::Create(GURL("https://site.test"));
-  mojo_config->decision_logic_url = GURL("http://site.test/");
+    auto auction_config = blink::mojom::AuctionAdConfig::New();
+    auction_config->seller = kOriginA;
 
-  bool callback_fired = false;
-  FinalizeAd(
-      /*guid=*/"1234", std::move(mojo_config),
-      base::BindLambdaForTesting([&](const absl::optional<GURL>& creative_url) {
-        ASSERT_FALSE(creative_url.has_value());
-        callback_fired = true;
-      }));
-  ASSERT_TRUE(callback_fired);
-}
+    auction_config->decision_logic_url = kUrlA.Resolve(kDecisionUrlPath);
+    auction_config->auction_ad_config_non_shared_params =
+        blink::mojom::AuctionAdConfigNonSharedParams::New();
+    auction_config->auction_ad_config_non_shared_params
+        ->interest_group_buyers = {kOriginA};
+    absl::optional<GURL> auction_result =
+        RunAdAuctionAndFlush(std::move(auction_config));
+    EXPECT_NE(auction_result, absl::nullopt);
+  }
 
-// An empty GUID should trigger any FinalizeAd request to fail.
-TEST_F(AdAuctionServiceImplTest, FinalizeAdRejectsMissingGuid) {
-  auto mojo_config = blink::mojom::AuctionAdConfig::New();
-  mojo_config->auction_ad_config_non_shared_params =
-      blink::mojom::AuctionAdConfigNonSharedParams::New();
-  mojo_config->seller = url::Origin::Create(GURL("https://site.test"));
-  mojo_config->decision_logic_url = GURL("https://site.test/");
-
-  bool callback_fired = false;
-  FinalizeAd(
-      /*guid=*/std::string(), std::move(mojo_config),
-      base::BindLambdaForTesting([&](const absl::optional<GURL>& creative_url) {
-        ASSERT_FALSE(creative_url.has_value());
-        callback_fired = true;
-      }));
-  ASSERT_TRUE(callback_fired);
+  task_environment()->FastForwardBy(base::Seconds(3));
+  // Three reports sent already. Reporting interval is set to 5s, and only 3s
+  // passed, so no next report was sent after one report was sent, i.e., all
+  // sent reports were sent in the same round in parallel.
+  EXPECT_EQ(network_responder_->ReportCount(), 3u);
+  EXPECT_TRUE(network_responder_->ReportSent("/report_seller_1"));
+  EXPECT_TRUE(network_responder_->ReportSent("/report_bidder_1"));
+  EXPECT_TRUE(network_responder_->ReportSent("/bidder_debug_win_1"));
+  // Fastforward to pass reporting interval (but less than two reporting
+  // intervals) so that the second round of reports are sent but the third
+  // round hasn't started.
+  task_environment()->FastForwardBy(base::Seconds(5));
+  // Three more reports were sent.
+  EXPECT_EQ(network_responder_->ReportCount(), 6u);
+  EXPECT_TRUE(network_responder_->ReportSent("/seller_debug_win_1"));
+  EXPECT_TRUE(network_responder_->ReportSent("/report_seller_2"));
+  EXPECT_TRUE(network_responder_->ReportSent("/report_bidder_2"));
+  // Fastforward enough time for all reports to be sent.
+  task_environment()->FastForwardBy(base::Seconds(6));
+  EXPECT_EQ(network_responder_->ReportCount(), 8u);
+  EXPECT_TRUE(network_responder_->ReportSent("/bidder_debug_win_2"));
+  EXPECT_TRUE(network_responder_->ReportSent("/seller_debug_win_2"));
 }
 
 }  // namespace content
diff --git a/content/browser/interest_group/interest_group_manager_impl.cc b/content/browser/interest_group/interest_group_manager_impl.cc
index 7c3a3bb..382ca696 100644
--- a/content/browser/interest_group/interest_group_manager_impl.cc
+++ b/content/browser/interest_group/interest_group_manager_impl.cc
@@ -30,6 +30,8 @@
 namespace content {
 
 namespace {
+// The maximum number of active report requests at a time.
+constexpr int kMaxActiveReportRequests = 5;
 // The maximum number of report URLs that can be stored in `report_requests_`
 // queue.
 constexpr int kMaxReportQueueLength = 100;
@@ -97,6 +99,7 @@
             in_memory ? base::FilePath() : path),
       auction_process_manager_(std::make_unique<AuctionProcessManager>()),
       update_manager_(this, std::move(url_loader_factory)),
+      max_active_report_requests_(kMaxActiveReportRequests),
       max_report_queue_length_(kMaxReportQueueLength),
       reporting_interval_(kReportingInterval) {}
 
@@ -346,17 +349,21 @@
   HandleReports(std::move(debug_win_report_urls), frame_origin,
                 client_security_state.Clone(), "DebugWinReport",
                 url_loader_factory);
-
-  // Avoid starting another SendReports() task while one is in-progress.
-  if (!send_reports_in_progress_) {
-    send_reports_in_progress_ = true;
+  if (!report_requests_.empty())
     SendReports();
-  }
 }
 
 void InterestGroupManagerImpl::SendReports() {
+  while (!report_requests_.empty() &&
+         num_active_ < max_active_report_requests_) {
+    num_active_++;
+    TrySendingOneReport();
+  }
+}
+
+void InterestGroupManagerImpl::TrySendingOneReport() {
   if (report_requests_.empty()) {
-    send_reports_in_progress_ = false;
+    num_active_--;
     return;
   }
 
@@ -387,15 +394,17 @@
 void InterestGroupManagerImpl::OnOneReportSent(
     std::unique_ptr<network::SimpleURLLoader> simple_url_loader,
     scoped_refptr<net::HttpResponseHeaders> response_headers) {
+  DCHECK_GT(num_active_, 0);
+
   if (!report_requests_.empty()) {
     base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
         FROM_HERE,
-        base::BindOnce(&InterestGroupManagerImpl::SendReports,
+        base::BindOnce(&InterestGroupManagerImpl::TrySendingOneReport,
                        weak_factory_.GetWeakPtr()),
         reporting_interval_);
-  } else {
-    send_reports_in_progress_ = false;
+    return;
   }
+  num_active_--;
 }
 
 void InterestGroupManagerImpl::set_max_report_queue_length_for_testing(
@@ -408,4 +417,9 @@
   reporting_interval_ = interval;
 }
 
+void InterestGroupManagerImpl::set_max_active_report_requests_for_testing(
+    int max_active_report_requests) {
+  max_active_report_requests_ = max_active_report_requests;
+}
+
 }  // namespace content
diff --git a/content/browser/interest_group/interest_group_manager_impl.h b/content/browser/interest_group/interest_group_manager_impl.h
index 17bc139..569b246 100644
--- a/content/browser/interest_group/interest_group_manager_impl.h
+++ b/content/browser/interest_group/interest_group_manager_impl.h
@@ -189,14 +189,19 @@
     auction_process_manager_ = std::move(auction_process_manager);
   }
 
-  // For testing *only*; changes the maximum number of report URLs that can be
-  // stored in `report_requests_` queue.
+  // For testing *only*; changes the maximum number of report requests that can
+  // be stored in `report_requests_` queue.
   void set_max_report_queue_length_for_testing(int max_queue_length);
 
   // For testing *only*; changes the time interval to wait before sending the
   // next report after sending one.
   void set_reporting_interval_for_testing(base::TimeDelta interval);
 
+  // For testing *only*; changes the maximum number of active report requests
+  // at a time.
+  void set_max_active_report_requests_for_testing(
+      int max_active_report_requests);
+
  private:
   // InterestGroupUpdateManager calls private members to write updates to the
   // database.
@@ -272,9 +277,13 @@
       network::mojom::ClientSecurityStatePtr client_security_state,
       const std::string& name,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+
+  // Calls TrySendingOneReport() when the queue is not empty and there are less
+  // active report requests than `max_active_report_requests_`.
+  void SendReports();
   // Dequeues and sends the first report request in `report_requests_` queue,
   // if the queue is not empty.
-  void SendReports();
+  void TrySendingOneReport();
   // Invoked when a report request completed.
   void OnOneReportSent(
       std::unique_ptr<network::SimpleURLLoader> simple_url_loader,
@@ -307,9 +316,13 @@
   // `max_report_queue_length` at the time of adding new entries.
   base::circular_deque<std::unique_ptr<ReportRequest>> report_requests_;
 
-  // Whether a task of SendReports() is being executed. Used to avoid invoking
-  // multiple SendReports() simultaneously.
-  bool send_reports_in_progress_ = false;
+  // Current number of active report requests.
+  int num_active_ = 0;
+
+  // The maximum number of active report requests at a time.
+  //
+  // Should *only* be changed by tests.
+  int max_active_report_requests_;
 
   // The maximum number of report requests that can be stored in queue
   // `report_requests_`.
diff --git a/content/browser/media/desktop_media_window_registry.h b/content/browser/media/desktop_media_window_registry.h
index 3387907f..db4f271 100644
--- a/content/browser/media/desktop_media_window_registry.h
+++ b/content/browser/media/desktop_media_window_registry.h
@@ -5,14 +5,13 @@
 #ifndef CONTENT_BROWSER_MEDIA_DESKTOP_MEDIA_WINDOW_REGISTRY_H_
 #define CONTENT_BROWSER_MEDIA_DESKTOP_MEDIA_WINDOW_REGISTRY_H_
 
+#include "content/public/browser/desktop_media_id.h"
 #include "ui/gfx/native_widget_types.h"
 
 namespace content {
 
 class DesktopMediaWindowRegistry {
  public:
-  using Id = intptr_t;
-
   static DesktopMediaWindowRegistry* GetInstance();
 
   DesktopMediaWindowRegistry(const DesktopMediaWindowRegistry&) = delete;
@@ -21,8 +20,8 @@
 
   virtual ~DesktopMediaWindowRegistry();
 
-  virtual Id RegisterWindow(gfx::NativeWindow window) = 0;
-  virtual gfx::NativeWindow GetWindowById(Id id) = 0;
+  virtual DesktopMediaID::Id RegisterWindow(gfx::NativeWindow window) = 0;
+  virtual gfx::NativeWindow GetWindowById(DesktopMediaID::Id id) = 0;
 
  protected:
   DesktopMediaWindowRegistry();
diff --git a/content/browser/media/desktop_media_window_registry_aura.cc b/content/browser/media/desktop_media_window_registry_aura.cc
index da8813f..7ce4e3c 100644
--- a/content/browser/media/desktop_media_window_registry_aura.cc
+++ b/content/browser/media/desktop_media_window_registry_aura.cc
@@ -25,7 +25,7 @@
   DesktopMediaWindowRegistryAura& operator=(
       const DesktopMediaWindowRegistryAura&) = delete;
 
-  Id RegisterWindow(gfx::NativeWindow window) final {
+  DesktopMediaID::Id RegisterWindow(gfx::NativeWindow window) final {
     base::IDMap<aura::Window*>::const_iterator it(&registered_windows_);
     for (; !it.IsAtEnd(); it.Advance()) {
       if (it.GetCurrentValue() == window)
@@ -36,7 +36,7 @@
     return registered_windows_.Add(window);
   }
 
-  gfx::NativeWindow GetWindowById(Id id) final {
+  gfx::NativeWindow GetWindowById(DesktopMediaID::Id id) final {
     return registered_windows_.Lookup(id);
   }
 
diff --git a/content/browser/media/desktop_media_window_registry_mac.mm b/content/browser/media/desktop_media_window_registry_mac.mm
index fd4664d..7231992 100644
--- a/content/browser/media/desktop_media_window_registry_mac.mm
+++ b/content/browser/media/desktop_media_window_registry_mac.mm
@@ -22,14 +22,16 @@
   DesktopMediaWindowRegistryMac& operator=(
       const DesktopMediaWindowRegistryMac&) = delete;
 
-  Id RegisterWindow(gfx::NativeWindow window) override {
-    // Note that DesktopMediaPickerViews in //chrome depends on the fact that
-    // the Id returned from this function is the NSWindow's windowNumber, but
-    // that invariant is *not* part of the general contract for DesktopMediaID.
+  // Note that DesktopMediaPickerViews in //chrome depends on the fact that
+  // the Id returned from this function is the NSWindow's windowNumber, but
+  // that invariant is *not* part of the general contract for DesktopMediaID.
+  DesktopMediaID::Id RegisterWindow(gfx::NativeWindow window) override {
+    // Ensure that we don't inadvertently crop IDs.
+    static_assert(sizeof(NSInteger) == sizeof(DesktopMediaID::Id));
     return window.GetNativeNSWindow().windowNumber;
   }
 
-  gfx::NativeWindow GetWindowById(Id id) override {
+  gfx::NativeWindow GetWindowById(DesktopMediaID::Id id) override {
     return gfx::NativeWindow([NSApp windowWithWindowNumber:id]);
   }
 
diff --git a/content/browser/permissions/permission_controller_impl.cc b/content/browser/permissions/permission_controller_impl.cc
index 2285af3..eb4d67e 100644
--- a/content/browser/permissions/permission_controller_impl.cc
+++ b/content/browser/permissions/permission_controller_impl.cc
@@ -111,6 +111,13 @@
   std::move(original_cb).Run(full_results);
 }
 
+void PermissionStatusCallbackWrapper(
+    base::OnceCallback<void(blink::mojom::PermissionStatus)> callback,
+    const std::vector<blink::mojom::PermissionStatus>& vector) {
+  DCHECK_EQ(1ul, vector.size());
+  std::move(callback).Run(vector.at(0));
+}
+
 }  // namespace
 
 PermissionControllerImpl::PermissionControllerImpl(
@@ -149,8 +156,7 @@
   content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
       subscription.render_process_id, subscription.render_frame_id);
   if (rfh) {
-    return GetPermissionStatusForFrame(subscription.permission, rfh,
-                                       subscription.requesting_origin);
+    return GetPermissionStatusForCurrentDocument(subscription.permission, rfh);
   }
 
   content::RenderProcessHost* rph =
@@ -270,36 +276,19 @@
   delegate->SetPermissionOverridesForDevTools(origin, current_overrides);
 }
 
-void PermissionControllerImpl::RequestPermission(
+void PermissionControllerImpl::RequestPermissionFromCurrentDocument(
     PermissionType permission,
     RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin,
     bool user_gesture,
     base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) {
-  NotifySchedulerAboutPermissionRequest(render_frame_host, permission);
-
-  absl::optional<blink::mojom::PermissionStatus> status_override =
-      devtools_permission_overrides_.Get(url::Origin::Create(requesting_origin),
-                                         permission);
-  if (status_override.has_value()) {
-    std::move(callback).Run(*status_override);
-    return;
-  }
-
-  PermissionControllerDelegate* delegate =
-      browser_context_->GetPermissionControllerDelegate();
-  if (!delegate) {
-    std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
-    return;
-  }
-  delegate->RequestPermission(permission, render_frame_host, requesting_origin,
-                              user_gesture, std::move(callback));
+  RequestPermissionsFromCurrentDocument(
+      {permission}, render_frame_host, user_gesture,
+      base::BindOnce(&PermissionStatusCallbackWrapper, std::move(callback)));
 }
 
-void PermissionControllerImpl::RequestPermissions(
+void PermissionControllerImpl::RequestPermissionsFromCurrentDocument(
     const std::vector<PermissionType>& permissions,
     RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin,
     bool user_gesture,
     base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
         callback) {
@@ -308,7 +297,7 @@
 
   std::vector<PermissionType> permissions_without_overrides;
   std::vector<absl::optional<blink::mojom::PermissionStatus>> results;
-  url::Origin origin = url::Origin::Create(requesting_origin);
+  url::Origin origin = render_frame_host->GetLastCommittedOrigin();
   for (const auto& permission : permissions) {
     absl::optional<blink::mojom::PermissionStatus> override_status =
         devtools_permission_overrides_.Get(origin, permission);
@@ -334,37 +323,10 @@
         blink::mojom::PermissionStatus::DENIED));
     return;
   }
-  delegate->RequestPermissions(permissions_without_overrides, render_frame_host,
-                               requesting_origin, user_gesture,
-                               std::move(wrapper));
-}
 
-void PermissionControllerImpl::RequestPermissionFromCurrentDocument(
-    PermissionType permission,
-    RenderFrameHost* render_frame_host,
-    bool user_gesture,
-    base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) {
-  // TODO(https://crbug.com/1271543): Add `RequestPermissionFromCurrentDocument`
-  // into `PermissionControllerDelegate` and use it here.
-  RequestPermission(
-      permission, render_frame_host,
-      PermissionUtil::GetLastCommittedOriginAsURL(render_frame_host),
-      user_gesture, std::move(callback));
-}
-
-void PermissionControllerImpl::RequestPermissionsFromCurrentDocument(
-    const std::vector<PermissionType>& permissions,
-    RenderFrameHost* render_frame_host,
-    bool user_gesture,
-    base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
-        callback) {
-  // TODO(https://crbug.com/1271543): Add
-  // `RequestPermissionsFromCurrentDocument` into `PermissionControllerDelegate`
-  // and use it here.
-  RequestPermissions(
-      permissions, render_frame_host,
-      PermissionUtil::GetLastCommittedOriginAsURL(render_frame_host),
-      user_gesture, std::move(callback));
+  delegate->RequestPermissionsFromCurrentDocument(
+      permissions_without_overrides, render_frame_host, user_gesture,
+      std::move(wrapper));
 }
 
 blink::mojom::PermissionStatus
@@ -430,25 +392,6 @@
                                        origin.GetURL());
 }
 
-blink::mojom::PermissionStatus
-PermissionControllerImpl::GetPermissionStatusForFrame(
-    PermissionType permission,
-    RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin) {
-  absl::optional<blink::mojom::PermissionStatus> status =
-      devtools_permission_overrides_.Get(url::Origin::Create(requesting_origin),
-                                         permission);
-  if (status)
-    return *status;
-
-  PermissionControllerDelegate* delegate =
-      browser_context_->GetPermissionControllerDelegate();
-  if (!delegate)
-    return blink::mojom::PermissionStatus::DENIED;
-  return delegate->GetPermissionStatusForFrame(permission, render_frame_host,
-                                               requesting_origin);
-}
-
 void PermissionControllerImpl::ResetPermission(PermissionType permission,
                                                const GURL& requesting_origin,
                                                const GURL& embedding_origin) {
diff --git a/content/browser/permissions/permission_controller_impl.h b/content/browser/permissions/permission_controller_impl.h
index 3de2847..15b9dfd 100644
--- a/content/browser/permissions/permission_controller_impl.h
+++ b/content/browser/permissions/permission_controller_impl.h
@@ -99,34 +99,13 @@
       base::OnceCallback<void(blink::mojom::PermissionStatus)> callback)
       override;
   void RequestPermissionsFromCurrentDocument(
-      const std::vector<PermissionType>& permission,
+      const std::vector<PermissionType>& permissions,
       RenderFrameHost* render_frame_host,
       bool user_gesture,
       base::OnceCallback<
           void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
       override;
 
-  void RequestPermissions(
-      const std::vector<PermissionType>& permission,
-      RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin,
-      bool user_gesture,
-      base::OnceCallback<
-          void(const std::vector<blink::mojom::PermissionStatus>&)> callback);
-
-  blink::mojom::PermissionStatus GetPermissionStatusForFrame(
-      PermissionType permission,
-      RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin);
-
-  void RequestPermission(
-      PermissionType permission,
-      RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin,
-      bool user_gesture,
-      base::OnceCallback<void(blink::mojom::PermissionStatus)> callback)
-      override;
-
   struct Subscription;
   using SubscriptionsMap =
       base::IDMap<std::unique_ptr<Subscription>, SubscriptionId>;
diff --git a/content/browser/permissions/permission_controller_impl_unittest.cc b/content/browser/permissions/permission_controller_impl_unittest.cc
index 34c6b80..db19394 100644
--- a/content/browser/permissions/permission_controller_impl_unittest.cc
+++ b/content/browser/permissions/permission_controller_impl_unittest.cc
@@ -41,10 +41,9 @@
   ~MockManagerWithRequests() override {}
   MOCK_METHOD(
       void,
-      RequestPermissions,
+      RequestPermissionsFromCurrentDocument,
       (const std::vector<PermissionType>& permission,
        RenderFrameHost* render_frame_host,
-       const GURL& requesting_origin,
        bool user_gesture,
        const base::OnceCallback<
            void(const std::vector<blink::mojom::PermissionStatus>&)> callback),
@@ -90,13 +89,11 @@
   void PermissionControllerRequestPermissions(
       const std::vector<PermissionType>& permission,
       RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin,
       bool user_gesture,
       base::OnceCallback<
           void(const std::vector<blink::mojom::PermissionStatus>&)> callback) {
-    permission_controller()->RequestPermissions(permission, render_frame_host,
-                                                requesting_origin, user_gesture,
-                                                std::move(callback));
+    permission_controller()->RequestPermissionsFromCurrentDocument(
+        permission, render_frame_host, user_gesture, std::move(callback));
   }
 
   blink::mojom::PermissionStatus GetPermissionStatusForWorker(
@@ -223,8 +220,14 @@
        {},
        /*expect_death=*/true}};
 
-  auto web_contents = base::WrapUnique(WebContentsTester::CreateTestWebContents(
-      WebContents::CreateParams(browser_context())));
+  std::unique_ptr<WebContents> web_contents(
+      WebContentsTester::CreateTestWebContents(
+          WebContents::CreateParams(browser_context())));
+
+  WebContentsTester* web_contents_tester =
+      WebContentsTester::For(web_contents.get());
+  web_contents_tester->NavigateAndCommit(GURL(kTestUrl));
+
   RenderFrameHost* rfh = web_contents->GetMainFrame();
   for (const auto& test_case : kTestCases) {
     // Need to reset overrides for each case to ensure delegation is as
@@ -238,7 +241,7 @@
 
     // Expect request permission call if override are missing.
     if (!test_case.delegated_permissions.empty()) {
-      auto forward_callbacks = testing::WithArg<4>(
+      auto forward_callbacks = testing::WithArg<3>(
           [&test_case](base::OnceCallback<void(
                            const std::vector<blink::mojom::PermissionStatus>&)>
                            callback) {
@@ -246,40 +249,42 @@
             return 0;
           });
       // Regular tests can set expectations.
-      if (!test_case.expect_death) {
-        EXPECT_CALL(
-            *mock_manager(),
-            RequestPermissions(
-                testing::ElementsAreArray(test_case.delegated_permissions), rfh,
-                kTestOrigin.GetURL(), true, testing::_))
-            .WillOnce(testing::Invoke(forward_callbacks));
-      } else {
+      if (test_case.expect_death) {
         // Death tests cannot track these expectations but arguments should be
         // forwarded to ensure death occurs.
         ON_CALL(*mock_manager(),
-                RequestPermissions(
+                RequestPermissionsFromCurrentDocument(
                     testing::ElementsAreArray(test_case.delegated_permissions),
-                    rfh, kTestOrigin.GetURL(), true, testing::_))
+                    rfh, true, testing::_))
             .WillByDefault(testing::Invoke(forward_callbacks));
+      } else {
+        EXPECT_CALL(
+            *mock_manager(),
+            RequestPermissionsFromCurrentDocument(
+                testing::ElementsAreArray(test_case.delegated_permissions), rfh,
+                true, testing::_))
+            .WillOnce(testing::Invoke(forward_callbacks));
       }
     } else {
       // There should be no call to delegate if all overrides are defined.
-      EXPECT_CALL(*mock_manager(), RequestPermissions).Times(0);
+      EXPECT_CALL(*mock_manager(), RequestPermissionsFromCurrentDocument)
+          .Times(0);
     }
-    if (!test_case.expect_death) {
-      base::MockCallback<RequestsCallback> callback;
-      EXPECT_CALL(callback,
-                  Run(testing::ElementsAreArray(test_case.expected_results)));
-      PermissionControllerRequestPermissions(
-          kTypesToQuery, rfh, kTestOrigin.GetURL(),
-          /*user_gesture=*/true, callback.Get());
-    } else {
+
+    if (test_case.expect_death) {
       ::testing::FLAGS_gtest_death_test_style = "threadsafe";
       base::MockCallback<RequestsCallback> callback;
       EXPECT_DEATH_IF_SUPPORTED(PermissionControllerRequestPermissions(
-                                    kTypesToQuery, rfh, kTestOrigin.GetURL(),
+                                    kTypesToQuery, rfh,
                                     /*user_gesture=*/true, callback.Get()),
                                 "");
+    } else {
+      base::MockCallback<RequestsCallback> callback;
+      EXPECT_CALL(callback,
+                  Run(testing::ElementsAreArray(test_case.expected_results)));
+      PermissionControllerRequestPermissions(kTypesToQuery, rfh,
+                                             /*user_gesture=*/true,
+                                             callback.Get());
     }
   }
 }
diff --git a/content/browser/permissions/permission_service_impl.cc b/content/browser/permissions/permission_service_impl.cc
index 124e5fcb..d2b12f7 100644
--- a/content/browser/permissions/permission_service_impl.cc
+++ b/content/browser/permissions/permission_service_impl.cc
@@ -125,8 +125,8 @@
 
   int pending_request_id = pending_requests_.Add(std::move(pending_request));
   PermissionControllerImpl::FromBrowserContext(browser_context)
-      ->RequestPermissions(
-          types, context_->render_frame_host(), origin_.GetURL(), user_gesture,
+      ->RequestPermissionsFromCurrentDocument(
+          types, context_->render_frame_host(), user_gesture,
           base::BindOnce(&PermissionServiceImpl::OnRequestPermissionsResponse,
                          weak_factory_.GetWeakPtr(), pending_request_id));
 }
diff --git a/content/browser/permissions/permission_util.cc b/content/browser/permissions/permission_util.cc
index 5e1a977..e225272 100644
--- a/content/browser/permissions/permission_util.cc
+++ b/content/browser/permissions/permission_util.cc
@@ -23,10 +23,10 @@
 
   content::WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(render_frame_host);
-  // If `allow_universal_access_from_file_urls` flag is enabled, a file can
-  // introduce discrepancy between GetLastCommittedURL and
-  // GetLastCommittedOrigin. In that case GetLastCommittedURL should be used
-  // for requesting and verifying permissions.
+  // If `allow_universal_access_from_file_urls` flag is enabled, a file:/// can
+  // change its url via history.pushState/replaceState to any other url,
+  // including about:blank. To avoid user confusion we should always use a
+  // visible url, in other words `GetLastCommittedURL`.
   if (web_contents->GetOrCreateWebPreferences()
           .allow_universal_access_from_file_urls &&
       render_frame_host->GetLastCommittedOrigin().GetURL().SchemeIsFile()) {
diff --git a/content/browser/push_messaging/push_messaging_manager.cc b/content/browser/push_messaging/push_messaging_manager.cc
index 046330be..74ad8c3e4 100644
--- a/content/browser/push_messaging/push_messaging_manager.cc
+++ b/content/browser/push_messaging/push_messaging_manager.cc
@@ -330,11 +330,14 @@
           url::Origin requesting_origin = data.requesting_origin;
           bool user_gesture = data.user_gesture;
 
+          DCHECK_EQ(data.requesting_origin,
+                    render_frame_host->GetLastCommittedOrigin());
+
           render_frame_host->GetBrowserContext()
               ->GetPermissionController()
-              ->RequestPermission(
+              ->RequestPermissionFromCurrentDocument(
                   blink::PermissionType::NOTIFICATIONS, render_frame_host,
-                  requesting_origin.GetURL(), user_gesture,
+                  user_gesture,
                   base::BindOnce(
                       &PushMessagingManager::DidRequestPermissionInIncognito,
                       AsWeakPtr(), std::move(data)));
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 6dc1f0a4..a092ccb 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -385,6 +385,14 @@
 base::LazyInstance<RoutingIDFrameMap>::DestructorAtExit g_routing_id_frame_map =
     LAZY_INSTANCE_INITIALIZER;
 
+// A global set of all sandboxed RenderFrameHosts that could be isolated from
+// the rest of their SiteInstance.
+typedef std::unordered_set<GlobalRenderFrameHostId,
+                           GlobalRenderFrameHostIdHasher>
+    RoutingIDIsolatableSandboxedIframesSet;
+base::LazyInstance<RoutingIDIsolatableSandboxedIframesSet>::DestructorAtExit
+    g_routing_id_isolatable_sandboxed_iframes_set = LAZY_INSTANCE_INITIALIZER;
+
 using TokenFrameMap = std::unordered_map<blink::LocalFrameToken,
                                          RenderFrameHostImpl*,
                                          blink::LocalFrameToken::Hasher>;
@@ -1577,6 +1585,10 @@
   g_routing_id_frame_map.Get().erase(
       GlobalRenderFrameHostId(GetProcess()->GetID(), routing_id_));
 
+  // Remove this object from the isolatable sandboxed iframe set as well, if
+  // necessary.
+  g_routing_id_isolatable_sandboxed_iframes_set.Get().erase(GetGlobalId());
+
   // When a RenderFrameHostImpl is deleted, it may still contain children. This
   // can happen with the unload timer. It causes a RenderFrameHost to delete
   // itself even if it is still waiting for its children to complete their
@@ -10835,6 +10847,112 @@
   return request->GetReferrer().Clone();
 }
 
+// static
+// This function logs metrics about potentially isolatable sandboxed iframes
+// that are tracked through calls to UpdateIsolatableSandboxedIframeTracking().
+// In addition to reporting the number of potential OOPSIFs, it also reports the
+// number of unique origins encountered (to give insight into potential
+// behavior if a per-origin isolation model was implemented), and it counts the
+// actual number of RenderProcessHosts isolating OOPSIFs using the current
+// per-site isolation model.
+void RenderFrameHost::LogSandboxedIframesIsolationMetrics() {
+  RoutingIDIsolatableSandboxedIframesSet* oopsifs =
+      g_routing_id_isolatable_sandboxed_iframes_set.Pointer();
+
+  base::UmaHistogramCounts1000("SiteIsolation.IsolatableSandboxedIframes",
+                               oopsifs->size());
+
+  // Count the number of unique origins across all the isolatable sandboxed
+  // iframes. This will give us a sense of the potential process overhead if we
+  // chose a per-origin process model for isolating these frames instead of the
+  // per-site model we plan to use. We use the precursor SchemeHostPort rather
+  // than the url::Origin, which is always opaque in these cases.
+  {
+    std::set<SiteInfo> sandboxed_site_infos;
+    std::set<url::SchemeHostPort> sandboxed_origins;
+    for (auto rfh_global_id : *oopsifs) {
+      auto* rfhi = RenderFrameHostImpl::FromID(rfh_global_id);
+      DCHECK(rfhi->GetLastCommittedOrigin().opaque());
+      sandboxed_origins.insert(
+          rfhi->GetLastCommittedOrigin().GetTupleOrPrecursorTupleIfOpaque());
+      sandboxed_site_infos.insert(rfhi->GetSiteInstance()->GetSiteInfo());
+    }
+    base::UmaHistogramCounts1000(
+        "SiteIsolation.IsolatableSandboxedIframes.UniqueOrigins",
+        sandboxed_origins.size());
+    base::UmaHistogramCounts1000(
+        "SiteIsolation.IsolatableSandboxedIframes.UniqueSites",
+        sandboxed_site_infos.size());
+  }
+
+  // Walk the set and count the number of unique RenderProcessHosts. Using a set
+  // allows us to accurately measure process overhead, including cases where
+  // SiteInstances from multiple BrowsingInstances are coalesced into a single
+  // RenderProcess.
+  std::set<RenderProcessHost*> sandboxed_rphs;
+  for (auto rfh_global_id : *oopsifs) {
+    auto* rfhi = FromID(rfh_global_id);
+    DCHECK(rfhi);
+    auto* site_instance =
+        static_cast<SiteInstanceImpl*>(rfhi->GetSiteInstance());
+    DCHECK(site_instance->HasProcess());
+    if (site_instance->GetSiteInfo().is_sandboxed())
+      sandboxed_rphs.insert(site_instance->GetProcess());
+  }
+  // There should be no sandboxed RPHs if the feature isn't enabled.
+  DCHECK(SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled() ||
+         sandboxed_rphs.size() == 0);
+  base::UmaHistogramCounts1000(
+      "Memory.RenderProcessHost.Count.SandboxedIframeOverhead",
+      sandboxed_rphs.size());
+}
+
+void RenderFrameHostImpl::UpdateIsolatableSandboxedIframeTracking() {
+  RoutingIDIsolatableSandboxedIframesSet* oopsifs =
+      g_routing_id_isolatable_sandboxed_iframes_set.Pointer();
+  GlobalRenderFrameHostId global_id = GetGlobalId();
+
+  // Check if the flags are correct.
+  DCHECK(policy_container_host_);
+  bool frame_is_isolatable =
+      IsSandboxed(network::mojom::WebSandboxFlags::kOrigin);
+
+  if (frame_is_isolatable) {
+    // Limit the "isolatable" sandboxed frames to those that are either in the
+    // same SiteInstance as their parent/opener (and thus could be isolated), or
+    // that are already isolated due to sandbox flags.
+    GURL url = GetLastCommittedURL();
+    if (url.IsAboutBlank() || url.is_empty()) {
+      frame_is_isolatable = false;
+    } else {
+      // Since this frame could be a main frame, we need to consider the
+      // SiteInstance of either the parent or opener (if either exists) of this
+      // frame, to see if the url can be placed in an OOPSIF, i.e. it's not
+      // already isolated because of being cross-site.
+      RenderFrameHost* frame_owner = GetParent();
+      if (!frame_owner && frame_tree_node_->opener())
+        frame_owner = frame_tree_node_->opener()->current_frame_host();
+
+      if (!frame_owner) {
+        frame_is_isolatable = false;
+      } else if (GetSiteInstance()->GetSiteInfo().is_sandboxed()) {
+        DCHECK(frame_is_isolatable);
+      } else if (frame_owner->GetSiteInstance() != GetSiteInstance()) {
+        // If this host's SiteInstance isn't already marked as is_sandboxed
+        // (with a frame owner), and yet the SiteInstance doesn't match that of
+        // our parent/opener, then it is already isolated for some other reason
+        // (cross-site, origin-keyed, etc.).
+        frame_is_isolatable = false;
+      }
+    }
+  }
+
+  if (frame_is_isolatable)
+    oopsifs->insert(global_id);
+  else
+    oopsifs->erase(global_id);
+}
+
 bool RenderFrameHostImpl::DidCommitNavigationInternal(
     std::unique_ptr<NavigationRequest> navigation_request,
     mojom::DidCommitProvisionalLoadParamsPtr params,
@@ -11192,6 +11310,8 @@
   media_device_id_salt_base_ = BrowserContext::CreateRandomMediaDeviceIDSalt();
 
   accessibility_fatal_error_count_ = 0;
+
+  UpdateIsolatableSandboxedIframeTracking();
 }
 
 // TODO(arthursonzogni): Below, many NavigationRequest's objects are passed from
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index 22ddf51..3de87142 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -3114,6 +3114,22 @@
       mojom::DidCommitProvisionalLoadParamsPtr params,
       mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params);
 
+  // Updates tracking of potentially isolatable sandboxed iframes, i.e. iframes
+  // that could be isolated if features::kIsolateSandboxedIframes is enabled.
+  // A frame can only be an out-of-process sandboxed iframe (OOPSIF) if, in
+  // addition to the iframe being sandboxed, the url being committed is not
+  // about:blank and is same-site to the parent's site (i.e. is not already an
+  // OOPIF). Also, the sandbox permissions must not include 'allow-same-origin'.
+  // Anytime the commit is a potential OOPSIF, this RenderFrameHostImpl will be
+  // tracked in a global list from which we can determine how many potential
+  // OOPSIFs exist at any instant in time. Metrics based on the tracked
+  // isolatable frames are generated in LogSandboxedIframesIsolationMetrics()
+  // when it is called by the metrics recording codepath. Note: sandboxed main
+  // frames that have been opened by an OOPSIF are considered isolatable for the
+  // purposes of this function, since they could lead to process overhead under
+  // a per-origin isolation model. Assumes that `policy_container_host_` is set.
+  void UpdateIsolatableSandboxedIframeTracking();
+
   // Called when we receive the confirmation that a navigation committed in the
   // renderer. Used by both DidCommitSameDocumentNavigation and
   // DidCommitNavigation.
diff --git a/content/browser/renderer_host/transient_allow_popup.h b/content/browser/renderer_host/transient_allow_popup.h
index 4f3e9d3..24c82e06 100644
--- a/content/browser/renderer_host/transient_allow_popup.h
+++ b/content/browser/renderer_host/transient_allow_popup.h
@@ -18,8 +18,10 @@
  public:
   TransientAllowPopup();
 
-  // The lifespan should be just long enough to allow brief async script calls.
-  static constexpr base::TimeDelta kActivationLifespan = base::Seconds(1);
+  // The lifespan should be just long enough to allow brief async script calls
+  // and long enough for the OS to complete any transition (i.e. fullscreen)
+  // animations first.
+  static constexpr base::TimeDelta kActivationLifespan = base::Seconds(5);
 
   // Activate the transient state.
   void Activate();
diff --git a/content/common/font_list_win.cc b/content/common/font_list_win.cc
index 3511262..42f22bc 100644
--- a/content/common/font_list_win.cc
+++ b/content/common/font_list_win.cc
@@ -60,10 +60,10 @@
     if (!localized_name)
       localized_name = native_name;
 
-    auto font_item = std::make_unique<base::ListValue>();
-    font_item->Append(native_name.value());
-    font_item->Append(localized_name.value());
-    font_list->Append(std::move(font_item));
+    base::Value::List font_item;
+    font_item.Append(native_name.value());
+    font_item.Append(localized_name.value());
+    font_list->GetList().Append(std::move(font_item));
   }
 
   return font_list;
diff --git a/content/public/browser/desktop_media_id.h b/content/public/browser/desktop_media_id.h
index cad5f9f..c59b06e 100644
--- a/content/public/browser/desktop_media_id.h
+++ b/content/public/browser/desktop_media_id.h
@@ -21,7 +21,7 @@
  public:
   enum Type { TYPE_NONE, TYPE_SCREEN, TYPE_WINDOW, TYPE_WEB_CONTENTS };
 
-  typedef intptr_t Id;
+  using Id = intptr_t;
 
   // Represents an "unset" value for either |id| or |window_id|.
   static constexpr Id kNullId = 0;
@@ -67,8 +67,6 @@
   // it possible for both of these to be non-null, which means both IDs are
   // referring to the same logical window.
   Id id = kNullId;
-
-  // TODO(https://crbug.com/1304392): Change window ID to an integer.
   Id window_id = kNullId;
 
   // This records whether the desktop share has sound or not.
diff --git a/content/public/browser/permission_controller.h b/content/public/browser/permission_controller.h
index b00fb9f..d31c2be 100644
--- a/content/public/browser/permission_controller.h
+++ b/content/public/browser/permission_controller.h
@@ -39,16 +39,14 @@
 
   // Returns the status of the given |permission| for a worker on
   // |worker_origin| running in the renderer corresponding to
-  // |render_process_host|. Use this over GetPermissionStatus to correctly
-  // handle requests originating from workers.
+  // |render_process_host|.
   virtual blink::mojom::PermissionStatus GetPermissionStatusForWorker(
       blink::PermissionType permission,
       RenderProcessHost* render_process_host,
       const url::Origin& worker_origin) = 0;
 
   // Returns the permission status for the current document in the given
-  // RenderFrameHost. Use this over `DeprecatedGetPermissionStatus` whenever
-  // possible as this API takes into account the lifecycle state of a given
+  // RenderFrameHost. This API takes into account the lifecycle state of a given
   // document (i.e. whether it's in back-forward cache or being prerendered) in
   // addition to its origin.
   virtual blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
@@ -61,20 +59,10 @@
   GetPermissionStatusForOriginWithoutContext(blink::PermissionType permission,
                                              const url::Origin& origin) = 0;
 
-  // Requests the permission for a given requesting_origin. Prefer
-  // `RequestPermissionFromCurrentDocument` whenever possible.
-  virtual void RequestPermission(
-      blink::PermissionType permission,
-      RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin,
-      bool user_gesture,
-      base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) = 0;
-
   // Requests the permission from the current document in the given
-  // RenderFrameHost. Use this over `RequestPermission` whenever possible as
-  // this API takes into account the lifecycle state of a given document (i.e.
-  // whether it's in back-forward cache or being prerendered) in addition to its
-  // origin.
+  // RenderFrameHost. This API takes into account the lifecycle state of a given
+  // document (i.e. whether it's in back-forward cache or being prerendered) in
+  // addition to its origin.
   virtual void RequestPermissionFromCurrentDocument(
       blink::PermissionType permission,
       RenderFrameHost* render_frame_host,
@@ -82,10 +70,9 @@
       base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) = 0;
 
   // Requests permissions from the current document in the given
-  // RenderFrameHost. Use this over `RequestPermission` whenever possible as
-  // this API takes into account the lifecycle state of a given document (i.e.
-  // whether it's in back-forward cache or being prerendered) in addition to its
-  // origin.
+  // RenderFrameHost. This API takes into account the lifecycle state of a given
+  // document (i.e. whether it's in back-forward cache or being prerendered) in
+  // addition to its origin.
   virtual void RequestPermissionsFromCurrentDocument(
       const std::vector<blink::PermissionType>& permission,
       RenderFrameHost* render_frame_host,
diff --git a/content/public/browser/permission_controller_delegate.h b/content/public/browser/permission_controller_delegate.h
index e10df21..e91b4557 100644
--- a/content/public/browser/permission_controller_delegate.h
+++ b/content/public/browser/permission_controller_delegate.h
@@ -54,31 +54,32 @@
       base::OnceCallback<void(
           const std::vector<blink::mojom::PermissionStatus>&)> callback) = 0;
 
+  // Requests permissions from the current document in the given
+  // RenderFrameHost. Use this over `RequestPermission` whenever possible as
+  // this API takes into account the lifecycle state of a given document (i.e.
+  // whether it's in back-forward cache or being prerendered) in addition to its
+  // origin.
+  virtual void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<void(
+          const std::vector<blink::mojom::PermissionStatus>&)> callback) = 0;
+
   // Returns the permission status of a given requesting_origin/embedding_origin
   // tuple. This is not taking a RenderFrameHost because the call might happen
-  // outside of a frame context. Prefer GetPermissionStatusForFrame (below)
-  // whenever possible.
+  // outside of a frame context. Prefer GetPermissionStatusForCurrentDocument
+  // (below) whenever possible.
   virtual blink::mojom::PermissionStatus GetPermissionStatus(
       blink::PermissionType permission,
       const GURL& requesting_origin,
       const GURL& embedding_origin) = 0;
 
-  // Returns the permission status for a given frame. Use this over
-  // GetPermissionStatus whenever possible.
-  // TODO(raymes): Currently we still pass the |requesting_origin| as a separate
-  // parameter because we can't yet guarantee that it matches the last committed
-  // origin of the RenderFrameHost. See https://crbug.com/698985.
-  // Deprecated. Use `GetPermissionStatusForCurrentDocument` instead.
-  virtual blink::mojom::PermissionStatus GetPermissionStatusForFrame(
-      blink::PermissionType permission,
-      RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin) = 0;
-
   // Returns the permission status for the current document in the given
-  // RenderFrameHost. Use this over `GetPermissionStatusForFrame` and
-  // `GetPermissionStatus` whenever possible as this API takes into account the
-  // lifecycle state of a given document (i.e. whether it's in back-forward
-  // cache or being prerendered) in addition to its origin.
+  // RenderFrameHost. Use this over `GetPermissionStatus` whenever possible as
+  // this API takes into account the lifecycle state of a given document (i.e.
+  // whether it's in back-forward cache or being prerendered) in addition to its
+  // origin.
   virtual blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
       blink::PermissionType permission,
       RenderFrameHost* render_frame_host) = 0;
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index baab99d..a7a7565 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -167,6 +167,9 @@
       const base::android::JavaRef<jobject>& jrender_frame_host_android);
 #endif
 
+  // Logs UMA metrics related to isolatable sandboxed iframes.
+  static void LogSandboxedIframesIsolationMetrics();
+
   ~RenderFrameHost() override = default;
 
   // Returns the route id for this frame.
diff --git a/content/public/test/mock_permission_controller.cc b/content/public/test/mock_permission_controller.cc
index 79843dd..e5962c34 100644
--- a/content/public/test/mock_permission_controller.cc
+++ b/content/public/test/mock_permission_controller.cc
@@ -4,22 +4,12 @@
 
 #include "content/public/test/mock_permission_controller.h"
 
-#include "third_party/blink/public/common/permissions/permission_utils.h"
-#include "url/gurl.h"
-
 namespace content {
 
 MockPermissionController::MockPermissionController() = default;
 
 MockPermissionController::~MockPermissionController() = default;
 
-void MockPermissionController::RequestPermission(
-    blink::PermissionType permission,
-    RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin,
-    bool user_gesture,
-    base::OnceCallback<void(blink::mojom::PermissionStatus)> callback) {}
-
 void MockPermissionController::RequestPermissionFromCurrentDocument(
     blink::PermissionType permission,
     RenderFrameHost* render_frame_host,
diff --git a/content/public/test/mock_permission_controller.h b/content/public/test/mock_permission_controller.h
index 16233da..e8c8c11 100644
--- a/content/public/test/mock_permission_controller.h
+++ b/content/public/test/mock_permission_controller.h
@@ -8,8 +8,6 @@
 #include "content/public/browser/permission_controller.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
-class GURL;
-
 namespace blink {
 enum class PermissionType;
 }
@@ -31,10 +29,6 @@
   ~MockPermissionController() override;
 
   // PermissionController:
-  MOCK_METHOD3(DeprecatedGetPermissionStatus,
-               blink::mojom::PermissionStatus(blink::PermissionType permission,
-                                              const GURL& requesting_origin,
-                                              const GURL& embedding_origin));
   MOCK_METHOD3(
       GetPermissionStatusForWorker,
       blink::mojom::PermissionStatus(blink::PermissionType permission,
@@ -48,13 +42,6 @@
       GetPermissionStatusForOriginWithoutContext,
       blink::mojom::PermissionStatus(blink::PermissionType permission,
                                      const url::Origin& requesting_origin));
-  void RequestPermission(
-      blink::PermissionType permission,
-      RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin,
-      bool user_gesture,
-      base::OnceCallback<void(blink::mojom::PermissionStatus)> callback)
-      override;
   void RequestPermissionFromCurrentDocument(
       blink::PermissionType permission,
       RenderFrameHost* render_frame_host,
diff --git a/content/public/test/mock_permission_manager.cc b/content/public/test/mock_permission_manager.cc
index 2c983eb..c0ca0da6 100644
--- a/content/public/test/mock_permission_manager.cc
+++ b/content/public/test/mock_permission_manager.cc
@@ -28,4 +28,14 @@
     base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
         callback) {}
 
+void MockPermissionManager::ResetPermission(blink::PermissionType permission,
+                                            const GURL& requesting_origin,
+                                            const GURL& embedding_origin) {}
+
+void MockPermissionManager::RequestPermissionsFromCurrentDocument(
+    const std::vector<blink::PermissionType>& permissions,
+    content::RenderFrameHost* render_frame_host,
+    bool user_gesture,
+    base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
+        callback) {}
 }  // namespace content
diff --git a/content/public/test/mock_permission_manager.h b/content/public/test/mock_permission_manager.h
index 285f2f1..f36cb43 100644
--- a/content/public/test/mock_permission_manager.h
+++ b/content/public/test/mock_permission_manager.h
@@ -30,11 +30,6 @@
                blink::mojom::PermissionStatus(blink::PermissionType permission,
                                               const GURL& requesting_origin,
                                               const GURL& embedding_origin));
-  MOCK_METHOD3(GetPermissionStatusForFrame,
-               blink::mojom::PermissionStatus(
-                   blink::PermissionType permission,
-                   content::RenderFrameHost* render_frame_host,
-                   const GURL& requesting_origin));
   MOCK_METHOD2(GetPermissionStatusForCurrentDocument,
                blink::mojom::PermissionStatus(
                    blink::PermissionType permission,
@@ -61,7 +56,14 @@
       override;
   void ResetPermission(blink::PermissionType permission,
                        const GURL& requesting_origin,
-                       const GURL& embedding_origin) override {}
+                       const GURL& embedding_origin) override;
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<
+          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+      override;
   MOCK_METHOD5(SubscribePermissionStatusChange,
                SubscriptionId(
                    blink::PermissionType permission,
diff --git a/content/shell/browser/shell_permission_manager.cc b/content/shell/browser/shell_permission_manager.cc
index 807050b..0b62b1b2 100644
--- a/content/shell/browser/shell_permission_manager.cc
+++ b/content/shell/browser/shell_permission_manager.cc
@@ -117,6 +117,26 @@
     const GURL& embedding_origin) {
 }
 
+void ShellPermissionManager::RequestPermissionsFromCurrentDocument(
+    const std::vector<PermissionType>& permissions,
+    content::RenderFrameHost* render_frame_host,
+    bool user_gesture,
+    base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
+        callback) {
+  if (render_frame_host->IsNestedWithinFencedFrame()) {
+    std::move(callback).Run(std::vector<blink::mojom::PermissionStatus>(
+        permissions.size(), blink::mojom::PermissionStatus::DENIED));
+    return;
+  }
+  std::vector<blink::mojom::PermissionStatus> result;
+  for (const auto& permission : permissions) {
+    result.push_back(IsAllowlistedPermissionType(permission)
+                         ? blink::mojom::PermissionStatus::GRANTED
+                         : blink::mojom::PermissionStatus::DENIED);
+  }
+  std::move(callback).Run(result);
+}
+
 blink::mojom::PermissionStatus ShellPermissionManager::GetPermissionStatus(
     PermissionType permission,
     const GURL& requesting_origin,
@@ -135,28 +155,17 @@
 }
 
 blink::mojom::PermissionStatus
-ShellPermissionManager::GetPermissionStatusForFrame(
-    PermissionType permission,
-    content::RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin) {
-  if (render_frame_host->IsNestedWithinFencedFrame())
-    return blink::mojom::PermissionStatus::DENIED;
-  return GetPermissionStatus(
-      permission, requesting_origin,
-      permissions::PermissionUtil::GetLastCommittedOriginAsURL(
-          render_frame_host->GetMainFrame()));
-}
-
-blink::mojom::PermissionStatus
 ShellPermissionManager::GetPermissionStatusForCurrentDocument(
     PermissionType permission,
     content::RenderFrameHost* render_frame_host) {
   if (render_frame_host->IsNestedWithinFencedFrame())
     return blink::mojom::PermissionStatus::DENIED;
   return GetPermissionStatus(
-      permission, render_frame_host->GetLastCommittedOrigin().GetURL(),
+      permission,
       permissions::PermissionUtil::GetLastCommittedOriginAsURL(
-          render_frame_host));
+          render_frame_host),
+      permissions::PermissionUtil::GetLastCommittedOriginAsURL(
+          render_frame_host->GetMainFrame()));
 }
 
 blink::mojom::PermissionStatus
diff --git a/content/shell/browser/shell_permission_manager.h b/content/shell/browser/shell_permission_manager.h
index 8de7fe74..cf6d8ab 100644
--- a/content/shell/browser/shell_permission_manager.h
+++ b/content/shell/browser/shell_permission_manager.h
@@ -42,14 +42,17 @@
   void ResetPermission(blink::PermissionType permission,
                        const GURL& requesting_origin,
                        const GURL& embedding_origin) override;
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<
+          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+      override;
   blink::mojom::PermissionStatus GetPermissionStatus(
       blink::PermissionType permission,
       const GURL& requesting_origin,
       const GURL& embedding_origin) override;
-  blink::mojom::PermissionStatus GetPermissionStatusForFrame(
-      blink::PermissionType permission,
-      content::RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin) override;
   blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
       blink::PermissionType permission,
       content::RenderFrameHost* render_frame_host) override;
diff --git a/content/web_test/browser/web_test_permission_manager.cc b/content/web_test/browser/web_test_permission_manager.cc
index 0797d68..6828db9 100644
--- a/content/web_test/browser/web_test_permission_manager.cc
+++ b/content/web_test/browser/web_test_permission_manager.cc
@@ -15,9 +15,30 @@
 #include "content/public/browser/web_contents.h"
 #include "content/web_test/browser/web_test_content_browser_client.h"
 #include "third_party/blink/public/common/permissions/permission_utils.h"
+#include "third_party/blink/public/common/web_preferences/web_preferences.h"
 
 namespace content {
 
+namespace {
+GURL GetLastCommittedOriginAsURL(content::RenderFrameHost* render_frame_host) {
+  DCHECK(render_frame_host);
+
+  content::WebContents* web_contents =
+      content::WebContents::FromRenderFrameHost(render_frame_host);
+  // If `allow_universal_access_from_file_urls` flag is enabled, a file can
+  // introduce discrepancy between GetLastCommittedURL and
+  // GetLastCommittedOrigin. In that case GetLastCommittedURL should be used
+  // for requesting and verifying permissions.
+  if (web_contents->GetOrCreateWebPreferences()
+          .allow_universal_access_from_file_urls &&
+      render_frame_host->GetLastCommittedOrigin().GetURL().SchemeIsFile()) {
+    return render_frame_host->GetLastCommittedURL().DeprecatedGetOriginAsURL();
+  }
+
+  return render_frame_host->GetLastCommittedOrigin().GetURL();
+}
+}  // namespace
+
 struct WebTestPermissionManager::Subscription {
   PermissionDescription permission;
   base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback;
@@ -66,11 +87,9 @@
     return;
   }
 
-  std::move(callback).Run(
-      GetPermissionStatus(permission, requesting_origin,
-                          WebContents::FromRenderFrameHost(render_frame_host)
-                              ->GetLastCommittedURL()
-                              .DeprecatedGetOriginAsURL()));
+  std::move(callback).Run(GetPermissionStatus(
+      permission, requesting_origin,
+      GetLastCommittedOriginAsURL(render_frame_host->GetMainFrame())));
 }
 
 void WebTestPermissionManager::RequestPermissions(
@@ -90,9 +109,7 @@
   std::vector<blink::mojom::PermissionStatus> result;
   result.reserve(permissions.size());
   const GURL& embedding_origin =
-      WebContents::FromRenderFrameHost(render_frame_host)
-          ->GetLastCommittedURL()
-          .DeprecatedGetOriginAsURL();
+      GetLastCommittedOriginAsURL(render_frame_host->GetMainFrame());
   for (const auto& permission : permissions) {
     result.push_back(
         GetPermissionStatus(permission, requesting_origin, embedding_origin));
@@ -115,6 +132,33 @@
   permissions_.erase(it);
 }
 
+void WebTestPermissionManager::RequestPermissionsFromCurrentDocument(
+    const std::vector<blink::PermissionType>& permissions,
+    content::RenderFrameHost* render_frame_host,
+    bool user_gesture,
+    base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
+        callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (render_frame_host->IsNestedWithinFencedFrame()) {
+    std::move(callback).Run(std::vector<blink::mojom::PermissionStatus>(
+        permissions.size(), blink::mojom::PermissionStatus::DENIED));
+    return;
+  }
+
+  std::vector<blink::mojom::PermissionStatus> result;
+  result.reserve(permissions.size());
+  const GURL& requesting_origin =
+      GetLastCommittedOriginAsURL(render_frame_host);
+  const GURL& embedding_origin =
+      GetLastCommittedOriginAsURL(render_frame_host->GetMainFrame());
+  for (const auto& permission : permissions) {
+    result.push_back(
+        GetPermissionStatus(permission, requesting_origin, embedding_origin));
+  }
+
+  std::move(callback).Run(result);
+}
+
 blink::mojom::PermissionStatus WebTestPermissionManager::GetPermissionStatus(
     blink::PermissionType permission,
     const GURL& requesting_origin,
@@ -143,30 +187,14 @@
 }
 
 blink::mojom::PermissionStatus
-WebTestPermissionManager::GetPermissionStatusForFrame(
-    blink::PermissionType permission,
-    content::RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin) {
-  if (render_frame_host->IsNestedWithinFencedFrame())
-    return blink::mojom::PermissionStatus::DENIED;
-  return GetPermissionStatus(
-      permission, requesting_origin,
-      content::WebContents::FromRenderFrameHost(render_frame_host)
-          ->GetLastCommittedURL()
-          .DeprecatedGetOriginAsURL());
-}
-
-blink::mojom::PermissionStatus
 WebTestPermissionManager::GetPermissionStatusForCurrentDocument(
     blink::PermissionType permission,
     content::RenderFrameHost* render_frame_host) {
   if (render_frame_host->IsNestedWithinFencedFrame())
     return blink::mojom::PermissionStatus::DENIED;
   return GetPermissionStatus(
-      permission, render_frame_host->GetLastCommittedOrigin().GetURL(),
-      content::WebContents::FromRenderFrameHost(render_frame_host)
-          ->GetLastCommittedURL()
-          .DeprecatedGetOriginAsURL());
+      permission, GetLastCommittedOriginAsURL(render_frame_host),
+      GetLastCommittedOriginAsURL(render_frame_host->GetMainFrame()));
 }
 
 blink::mojom::PermissionStatus
@@ -189,10 +217,8 @@
   // If the request is from a worker, it won't have a RFH.
   GURL embedding_origin = requesting_origin;
   if (render_frame_host) {
-    WebContents* web_contents =
-        WebContents::FromRenderFrameHost(render_frame_host);
     embedding_origin =
-        web_contents->GetLastCommittedURL().DeprecatedGetOriginAsURL();
+        GetLastCommittedOriginAsURL(render_frame_host->GetMainFrame());
   }
 
   auto subscription = std::make_unique<Subscription>();
diff --git a/content/web_test/browser/web_test_permission_manager.h b/content/web_test/browser/web_test_permission_manager.h
index 012d98ba..998ab38b1 100644
--- a/content/web_test/browser/web_test_permission_manager.h
+++ b/content/web_test/browser/web_test_permission_manager.h
@@ -52,14 +52,17 @@
   void ResetPermission(blink::PermissionType permission,
                        const GURL& requesting_origin,
                        const GURL& embedding_origin) override;
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<
+          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+      override;
   blink::mojom::PermissionStatus GetPermissionStatus(
       blink::PermissionType permission,
       const GURL& requesting_origin,
       const GURL& embedding_origin) override;
-  blink::mojom::PermissionStatus GetPermissionStatusForFrame(
-      blink::PermissionType permission,
-      content::RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin) override;
   blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
       blink::PermissionType permission,
       content::RenderFrameHost* render_frame_host) override;
diff --git a/docs/patterns/builder-and-parameter-bundle.md b/docs/patterns/builder-and-parameter-bundle.md
new file mode 100644
index 0000000..37368b26
--- /dev/null
+++ b/docs/patterns/builder-and-parameter-bundle.md
@@ -0,0 +1,189 @@
+# The Builder & Parameter Bundle Patterns
+
+The builder and parameter bundle patterns allow for giving a class a lot of
+configuration options at compile time, while leaving the runtime API small and
+the runtime constraints clear.
+
+Suppose that you are implementing a new class C, which has a name, a color, a
+size, and a URL associated with it, along with a handful of boolean parameters,
+each of which default to false. All of these values should be set before the C
+is actually used for anything. That class might look like this:
+
+    class C {
+     public:
+      // Invariant: none of the members can change after you call Init().
+      void Init();
+
+     private:
+      const string name_;
+      const gfx::Color color_;
+      const gfx::Size size_;
+      const GURL url_;
+
+      const bool is_cool_ = false;
+      const bool is_nice_ = false;
+      const bool is_friendly = false;
+    };
+
+There are three ways you might choose to make this class configurable:
+
+1. Have the constructor take initial values for all of these arguments, or even
+   have several constructors which take different subsets of the arguments.
+2. Have the constructor take no arguments, and instead expose setters for all of
+   these values, and enforce the invariant of DoStuff() some other way.
+3. Have the constructor take values for all the arguments with no sensible
+   default, and expose setters for the values that do have sensible defaults.
+
+Most classes end up doing one of these, and have an API that looks roughly like
+this:
+
+    class C {
+     public:
+      C(string name, gfx::Color color, gfx::Size size, GURL url);
+
+      void Init();
+
+      void set_is_cool(bool is_cool) { is_cool_ = is_cool; }
+      void set_is_nice(bool is_nice) { is_nice_ = is_nice; }
+      void set_is_friendly(bool is_friendly) { is_friendly_ = is_friendly; }
+
+     private:
+      ...
+      // Note that these now have to be non-const, even though they are
+      // logically const, because the setters are exposed to mutate them before
+      // use.
+      bool is_cool_;
+      bool is_nice_;
+      bool is_friendly_;
+    };
+
+Your class is forced into either:
+
+* Exposing every configuration option as a constructor argument, or
+* Allowing some things that are configurable only at construction to be set
+  any time after construction, with errors caught at runtime
+
+The builder pattern (and the parameter bundle pattern, a simpler relative) offer
+a way out of this bind.
+
+## Parameter Bundles
+
+A parameter bundle is an object that encapsulates all the parameters to another
+method, often to a constructor. For example, we might structure our class C like
+this:
+
+    class C {
+     public:
+      struct Params {
+        string name;
+        // ...
+      };
+
+      C(Params params);
+
+     private:
+      const string name_;
+      // ...
+    };
+
+As long as the params struct is well-structured this may be all you need, and it
+can often significantly simplify constructing complicated classes if callers are
+allowed to fill in only those parts of the param bundle that they care about.
+
+However, there's a problem: constructors are not allowed to fail in C++. That
+implies that it has to be impossible to *make* an invalid `C::Params`, because
+if we did pass such an invalid parameter bundle into `C::C()`, the constructor
+would have no way to signal failure. We really want to ensure that we can only
+get an instance of `C` that is configured in a valid way.
+
+We can do that by adding a factory function to C:
+
+    class C {
+     public:
+      unique_ptr<C> Make(Params params);
+
+     private:
+      // Since this is private, we can assume Params was validated by the
+      // factory function first.
+      C(Params params);
+    };
+
+But in the process, we've cluttered the public API of C up with a lot of the
+details about how one manufactures an instance of C. What if we could avoid
+doing that? Enter...
+
+## The Builder Pattern
+
+The key idea here is that instead of defining a `C::Params` class, we define a
+`C::Builder` class, which knows how to configure and then construct a new
+instance of `C`. That might look like this:
+
+    class C {
+     public:
+      class Builder;    // defined elsewhere
+
+     private:
+      friend class Builder;
+      C(Builder builder);    // only called from C::Builder
+    };
+
+and now our `Builder` class has an interface like this:
+
+    class Builder {
+     public:
+      Builder();
+      void set_name(string name);
+      void set_color(gfx::Color color):
+      // ...
+
+      std::unique_ptr<C> Build();
+    }
+
+To an extent, this is just a syntactic variation of the parameter bundle
+pattern, but it does allow for one really nice convenience technique. If,
+instead of returning void, we have our setters return a reference to the Builder
+object itself:
+
+    class Builder {
+     public:
+      Builder();
+      Builder& set_name(string name);
+      Builder& set_color(string name);
+      // ...
+
+      std::unique_ptr<C> Build();
+    }
+
+then instead of writing this:
+
+    C::Builder builder;
+    builder.set_name(name);
+    builder.set_color(color);
+    auto c = builder.Build();
+
+we can write this:
+
+    auto c = C::Builder().set_name(name)
+                         .set_color(color)
+                         .Build();
+
+which lets us avoid naming the temporary builder object.
+
+## Use This Pattern When
+
+* Your class has more than half a dozen or so configuration options, most of
+  which should not be changed once the object is "in use"
+* Your class has invalid sets of configuration options that should be prohibited
+* Your class has complicated configuration options of any sort that want runtime
+  checking (places you might have previously used the `bool Init()` pattern)
+
+## Alternatives / See Also
+
+* Regular constructor parameters
+* Instance variables with public setters
+
+## Examples in Chromium
+
+* [DialogModel::Builder](https://source.chromium.org/chromium/chromium/src/+/main:ui/base/models/dialog_model.h;drc=72186360334350c90b9b94515b3c82bea25e27ff;l=88)
+* [ChildThreadImpl::Builder](https://source.chromium.org/chromium/chromium/src/+/main:content/child/child_thread_impl.h;l=273?q=Builder%20file:%5C.h$%20-file:%5Ethird_party%2F&ss=chromium%2Fchromium%2Fsrc)
+* [TestingProfile::Builder](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/base/testing_profile.h;l=97?q=Builder%20file:%5C.h$%20-file:%5Ethird_party%2F&ss=chromium%2Fchromium%2Fsrc)
diff --git a/fuchsia/OWNERS b/fuchsia/OWNERS
index 7556bbf..ff7d7e1 100644
--- a/fuchsia/OWNERS
+++ b/fuchsia/OWNERS
@@ -1,5 +1,2 @@
 set noparent
 file://build/fuchsia/OWNERS
-
-per-file SECURITY_OWNERS=set noparent
-per-file SECURITY_OWNERS=file://build/fuchsia/SECURITY_OWNERS
diff --git a/fuchsia/engine/browser/web_engine_permission_delegate.cc b/fuchsia/engine/browser/web_engine_permission_delegate.cc
index b820948e..8a48f46 100644
--- a/fuchsia/engine/browser/web_engine_permission_delegate.cc
+++ b/fuchsia/engine/browser/web_engine_permission_delegate.cc
@@ -58,12 +58,25 @@
   NOTIMPLEMENTED() << ": " << static_cast<int>(permission);
 }
 
+void WebEnginePermissionDelegate::RequestPermissionsFromCurrentDocument(
+    const std::vector<blink::PermissionType>& permissions,
+    content::RenderFrameHost* render_frame_host,
+    bool user_gesture,
+    base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
+        callback) {
+  FrameImpl* frame = FrameImpl::FromRenderFrameHost(render_frame_host);
+  DCHECK(frame);
+  frame->permission_controller()->RequestPermissions(
+      permissions, render_frame_host->GetLastCommittedOrigin(), user_gesture,
+      std::move(callback));
+}
+
 blink::mojom::PermissionStatus WebEnginePermissionDelegate::GetPermissionStatus(
     blink::PermissionType permission,
     const GURL& requesting_origin,
     const GURL& embedding_origin) {
-  // Although GetPermissionStatusForFrame() should be used for most permissions,
-  // some use cases (e.g., BACKGROUND_SYNC) do not have a frame.
+  // Although GetPermissionStatusForCurrentDocument() should be used for most
+  // permissions, some use cases (e.g., BACKGROUND_SYNC) do not have a frame.
   //
   // TODO(crbug.com/1063094): Handle frame-less permission status checks in the
   // PermissionManager API. Until then, reject such requests.
@@ -71,17 +84,6 @@
 }
 
 blink::mojom::PermissionStatus
-WebEnginePermissionDelegate::GetPermissionStatusForFrame(
-    blink::PermissionType permission,
-    content::RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin) {
-  FrameImpl* frame = FrameImpl::FromRenderFrameHost(render_frame_host);
-  DCHECK(frame);
-  return frame->permission_controller()->GetPermissionState(
-      permission, url::Origin::Create(requesting_origin));
-}
-
-blink::mojom::PermissionStatus
 WebEnginePermissionDelegate::GetPermissionStatusForCurrentDocument(
     blink::PermissionType permission,
     content::RenderFrameHost* render_frame_host) {
diff --git a/fuchsia/engine/browser/web_engine_permission_delegate.h b/fuchsia/engine/browser/web_engine_permission_delegate.h
index cb153779..d2a143d1 100644
--- a/fuchsia/engine/browser/web_engine_permission_delegate.h
+++ b/fuchsia/engine/browser/web_engine_permission_delegate.h
@@ -42,14 +42,17 @@
   void ResetPermission(blink::PermissionType permission,
                        const GURL& requesting_origin,
                        const GURL& embedding_origin) override;
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<
+          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+      override;
   blink::mojom::PermissionStatus GetPermissionStatus(
       blink::PermissionType permission,
       const GURL& requesting_origin,
       const GURL& embedding_origin) override;
-  blink::mojom::PermissionStatus GetPermissionStatusForFrame(
-      blink::PermissionType permission,
-      content::RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin) override;
   blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
       blink::PermissionType permission,
       content::RenderFrameHost* render_frame_host) override;
diff --git a/fuchsia_webengine/DEPS b/fuchsia_webengine/DEPS
new file mode 100644
index 0000000..a8d5dde
--- /dev/null
+++ b/fuchsia_webengine/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  # Require explicit include rules for sub-directories.
+  "-fuchsia_webengine",
+]
\ No newline at end of file
diff --git a/fuchsia_webengine/DIR_METADATA b/fuchsia_webengine/DIR_METADATA
new file mode 100644
index 0000000..7bba048
--- /dev/null
+++ b/fuchsia_webengine/DIR_METADATA
@@ -0,0 +1,9 @@
+# Metadata information for this directory.
+#
+# For more information on DIR_METADATA files, see:
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
+#
+# For the schema of this file, see Metadata message:
+#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+
+mixins: "//build/fuchsia/COMMON_METADATA"
diff --git a/fuchsia_webengine/OWNERS b/fuchsia_webengine/OWNERS
new file mode 100644
index 0000000..ff7d7e1
--- /dev/null
+++ b/fuchsia_webengine/OWNERS
@@ -0,0 +1,2 @@
+set noparent
+file://build/fuchsia/OWNERS
diff --git a/fuchsia/README.md b/fuchsia_webengine/README.md
similarity index 69%
rename from fuchsia/README.md
rename to fuchsia_webengine/README.md
index 4338fcdf..138bd8b1 100644
--- a/fuchsia/README.md
+++ b/fuchsia_webengine/README.md
@@ -1,6 +1,8 @@
-# Chromium-based Fuchsia services
-This directory contains implementation code for various Fuchsia services living
-in the Chromium repository. To build Chromium on Fuchsia, check this
+# Fuchsia WebEngine and Runners
+This directory contains implementation code for Fuchsia WebEngine and code
+specifically related to it, including the Runners that use it.
+
+For general information about building Chromium on Fuchsia, see this
 [documentation](../docs/fuchsia/build_instructions.md).
 
 [TOC]
@@ -8,41 +10,24 @@
 ## Code organization
 Each of the following subdirectories contain code for a specific Fuchsia
 service:
-* `./engine` contains the WebEngine implementation. The WebEngine enables
+* `./engine` contains the WebEngine implementation. WebEngine enables
 Fuchsia applications to embed Chromium frames for rendering web content.
 * `./runners`contains implementations of Fuchsia `sys.runner`.
-    * `./runners/cast` Enables the Fuchsia system to launch cast applications.
+    * `./runners/cast` Enables the Fuchsia system to launch Cast applications.
     * `./runners/web` Enables the Fuchsia system to launch HTTP or HTTPS URLs.
-* `./media_receiver` contains an implementation for an Open Screen receiver.
-
-When writing a new Fuchsia service, it is recommended to create a new
-subdirectory under `//fuchsia` or a new subdirectory under `//fuchsia/runners`
-depending on the use case.
-
-The `./base` subdirectory contains common utilities used by more than one of
-the aforementioned Fuchsia services.
-
-The `./cipd` and `./fidl` subdirectories contain CIPD definitions and FIDL
-interface definitions, respectfully.
-
-### Namespacing
-
-Code that is not shared across multiple targets should live in the global
-namespace. Code that is shared across multiple targets should live in the
-`cr_fuchsia` namespace.
 
 ### Test code
 
-Under the `//fuchsia` directory , there are 3 major types of tests:
-* Unit tests: Exercises a single class in isolation, allowing full control
+There are 3 major types of tests within this directory:
+* Unit tests: Exercise a single class in isolation, allowing full control
   over the external environment of this class.
-* Browser tests: Spawns a full browser process along child processes. The test
+* Browser tests: Spawn a full browser process and its child processes. The test
   code is run inside the browser process, allowing for full access to the
-  browser code, but not other processes.
-* Integration tests: they exercise the published API of a Fuchsia component. For
-  instance, `//fuchsia/engine:web_engine_integration_tests` make use of the
-  `//fuchsia/engine:web_engine` component. The test code is run in a separate
-  process in a separate component, allowing only access to the published API of
+  browser code - but not other processes.
+* Integration tests: Exercise the published FIDL API of a Fuchsia Component. For
+  instance, `//fuchsia_webengine/engine:web_engine_integration_tests` make use of the
+  `//fuchsia_webengine/engine:web_engine` component. The test code runs in a separate
+  process in a separate Fuchsia Component, allowing only access to the published API of
   the component under test.
 
 Integration tests are more resource-intensive than browser tests, which are in
@@ -51,8 +36,9 @@
 
 As a general rule, test-only code should live in the same directory as the code
 under test with an explicit file name, either `fake_*`, `test_*`,
-`*_unittest.cc`, `*_ browser_test.cc` or `*_integration_test.cc`.
+`*_unittest.cc`, `*_ browsertest.cc` or `*_integration_test.cc`.
 
+## TODO(crbug.com/1081525): Update and/or move the remaining text as appropriate.
 Test code that is shared across components should live in a dedicated `test`
 directory, under the `cr_fuchsia` namespace. For instance, see the
 `//fuchsia/engine/test` directory, which contains code shared by all browser
diff --git a/gpu/command_buffer/client/webgpu_implementation.cc b/gpu/command_buffer/client/webgpu_implementation.cc
index 696e4ec..1429e2d 100644
--- a/gpu/command_buffer/client/webgpu_implementation.cc
+++ b/gpu/command_buffer/client/webgpu_implementation.cc
@@ -640,38 +640,8 @@
 }
 
 WGPUDevice WebGPUImplementation::DeprecatedEnsureDefaultDeviceSync() {
-  if (deprecated_default_device_ != nullptr) {
-    return deprecated_default_device_;
-  }
-
-  DLOG(WARNING) << "Using deprecated WebGPU device initialization";
-
-  base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
-  RequestAdapterAsync(
-      PowerPreference::kDefault, /* force_fallback_adapter */ false,
-      base::BindOnce(
-          [](WebGPUImplementation* self, WGPUDevice* result,
-             base::OnceCallback<void()> done, int32_t adapter_id,
-             const WGPUDeviceProperties& properties, const char* name) {
-            if (adapter_id < 0) {
-              std::move(done).Run();
-              return;
-            }
-            self->RequestDeviceAsync(
-                static_cast<uint32_t>(adapter_id), properties,
-                base::BindOnce(
-                    [](WGPUDevice* result, base::OnceCallback<void()> done,
-                       WGPUDevice device, const WGPUSupportedLimits*,
-                       const char*) {
-                      *result = device;
-                      std::move(done).Run();
-                    },
-                    result, std::move(done)));
-          },
-          this, &deprecated_default_device_, run_loop.QuitClosure()));
-  run_loop.Run();
-
-  return deprecated_default_device_;
+  NOTIMPLEMENTED();
+  return nullptr;
 }
 
 void WebGPUImplementation::AssociateMailbox(GLuint device_id,
diff --git a/gpu/command_buffer/client/webgpu_implementation.h b/gpu/command_buffer/client/webgpu_implementation.h
index 54a6c01..14449fe 100644
--- a/gpu/command_buffer/client/webgpu_implementation.h
+++ b/gpu/command_buffer/client/webgpu_implementation.h
@@ -145,7 +145,6 @@
 #if BUILDFLAG(USE_DAWN)
   scoped_refptr<DawnWireServices> dawn_wire_;
 #endif
-  WGPUDevice deprecated_default_device_ = nullptr;
 
   LogSettings log_settings_;
 
diff --git a/headless/lib/browser/headless_permission_manager.cc b/headless/lib/browser/headless_permission_manager.cc
index f6239f5c..e5c0ecd 100644
--- a/headless/lib/browser/headless_permission_manager.cc
+++ b/headless/lib/browser/headless_permission_manager.cc
@@ -54,6 +54,19 @@
     const GURL& requesting_origin,
     const GURL& embedding_origin) {}
 
+void HeadlessPermissionManager::RequestPermissionsFromCurrentDocument(
+    const std::vector<blink::PermissionType>& permissions,
+    content::RenderFrameHost* render_frame_host,
+    bool user_gesture,
+    base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)>
+        callback) {
+  // In headless mode we just pretent the user "closes" any permission prompt,
+  // without accepting or denying.
+  std::vector<blink::mojom::PermissionStatus> result(
+      permissions.size(), blink::mojom::PermissionStatus::ASK);
+  std::move(callback).Run(result);
+}
+
 blink::mojom::PermissionStatus HeadlessPermissionManager::GetPermissionStatus(
     blink::PermissionType permission,
     const GURL& requesting_origin,
@@ -62,14 +75,6 @@
 }
 
 blink::mojom::PermissionStatus
-HeadlessPermissionManager::GetPermissionStatusForFrame(
-    blink::PermissionType permission,
-    content::RenderFrameHost* render_frame_host,
-    const GURL& requesting_origin) {
-  return blink::mojom::PermissionStatus::ASK;
-}
-
-blink::mojom::PermissionStatus
 HeadlessPermissionManager::GetPermissionStatusForCurrentDocument(
     blink::PermissionType permission,
     content::RenderFrameHost* render_frame_host) {
diff --git a/headless/lib/browser/headless_permission_manager.h b/headless/lib/browser/headless_permission_manager.h
index fa7d88f..ed91c294 100644
--- a/headless/lib/browser/headless_permission_manager.h
+++ b/headless/lib/browser/headless_permission_manager.h
@@ -48,14 +48,17 @@
   void ResetPermission(blink::PermissionType permission,
                        const GURL& requesting_origin,
                        const GURL& embedding_origin) override;
+  void RequestPermissionsFromCurrentDocument(
+      const std::vector<blink::PermissionType>& permissions,
+      content::RenderFrameHost* render_frame_host,
+      bool user_gesture,
+      base::OnceCallback<
+          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
+      override;
   blink::mojom::PermissionStatus GetPermissionStatus(
       blink::PermissionType permission,
       const GURL& requesting_origin,
       const GURL& embedding_origin) override;
-  blink::mojom::PermissionStatus GetPermissionStatusForFrame(
-      blink::PermissionType permission,
-      content::RenderFrameHost* render_frame_host,
-      const GURL& requesting_origin) override;
   blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
       blink::PermissionType permission,
       content::RenderFrameHost* render_frame_host) override;
diff --git a/infra/config/generated/builders/ci/android-11-x86-rel/properties.json b/infra/config/generated/builders/ci/android-11-x86-rel/properties.json
index 8252801..d954e2f 100644
--- a/infra/config/generated/builders/ci/android-11-x86-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-11-x86-rel/properties.json
@@ -12,8 +12,5 @@
     ]
   },
   "builder_group": "chromium.android",
-  "recipe": "chromium",
-  "sheriff_rotations": [
-    "android"
-  ]
+  "recipe": "chromium"
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/ci/android-12-x64-rel/properties.json b/infra/config/generated/builders/ci/android-12-x64-rel/properties.json
index 8252801..d954e2f 100644
--- a/infra/config/generated/builders/ci/android-12-x64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-12-x64-rel/properties.json
@@ -12,8 +12,5 @@
     ]
   },
   "builder_group": "chromium.android",
-  "recipe": "chromium",
-  "sheriff_rotations": [
-    "android"
-  ]
+  "recipe": "chromium"
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/ci/android-cronet-arm-dbg/properties.json b/infra/config/generated/builders/ci/android-cronet-arm-dbg/properties.json
index d954e2f..1c941b8 100644
--- a/infra/config/generated/builders/ci/android-cronet-arm-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-arm-dbg/properties.json
@@ -1,4 +1,57 @@
 {
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "android-cronet-arm-dbg",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "build_gs_bucket": "chromium-android-archive",
+              "builder_group": "chromium.android",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_android_config": {
+                "config": "main_builder"
+              },
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "cronet_builder",
+                  "mb"
+                ],
+                "build_config": "Debug",
+                "config": "android",
+                "target_bits": 32,
+                "target_platform": "android"
+              },
+              "legacy_gclient_config": {
+                "apply_configs": [
+                  "android",
+                  "enable_reclient"
+                ],
+                "config": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "ci",
+          "builder": "android-cronet-arm-dbg",
+          "project": "chromium"
+        }
+      ],
+      "mirroring_builder_group_and_names": [
+        {
+          "builder": "android-cronet-arm-dbg",
+          "group": "tryserver.chromium.android"
+        }
+      ]
+    }
+  },
   "$build/reclient": {
     "instance": "rbe-chromium-trusted",
     "jobs": 500,
diff --git a/infra/config/generated/builders/ci/chromeos-amd64-generic-dbg/properties.json b/infra/config/generated/builders/ci/chromeos-amd64-generic-dbg/properties.json
index 20179b4..b63262e 100644
--- a/infra/config/generated/builders/ci/chromeos-amd64-generic-dbg/properties.json
+++ b/infra/config/generated/builders/ci/chromeos-amd64-generic-dbg/properties.json
@@ -1,4 +1,56 @@
 {
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "chromeos-amd64-generic-dbg",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "build_gs_bucket": "chromium-chromiumos-archive",
+              "builder_group": "chromium.chromiumos",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
+                "build_config": "Debug",
+                "config": "chromium",
+                "target_arch": "intel",
+                "target_bits": 64,
+                "target_cros_boards": [
+                  "amd64-generic"
+                ],
+                "target_platform": "chromeos"
+              },
+              "legacy_gclient_config": {
+                "apply_configs": [
+                  "chromeos"
+                ],
+                "config": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "ci",
+          "builder": "chromeos-amd64-generic-dbg",
+          "project": "chromium"
+        }
+      ],
+      "mirroring_builder_group_and_names": [
+        {
+          "builder": "chromeos-amd64-generic-dbg",
+          "group": "tryserver.chromium.chromiumos"
+        }
+      ]
+    }
+  },
   "$build/reclient": {
     "instance": "rbe-chromium-trusted",
     "jobs": 500,
diff --git a/infra/config/generated/builders/ci/mac-arm64-archive-dbg/properties.json b/infra/config/generated/builders/ci/mac-arm64-archive-dbg/properties.json
index fa75a041..fcb233be0 100644
--- a/infra/config/generated/builders/ci/mac-arm64-archive-dbg/properties.json
+++ b/infra/config/generated/builders/ci/mac-arm64-archive-dbg/properties.json
@@ -1,4 +1,42 @@
 {
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "mac-arm64-archive-dbg",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "builder_group": "chromium",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "clobber",
+                  "mb"
+                ],
+                "build_config": "Debug",
+                "config": "chromium",
+                "target_bits": 64
+              },
+              "legacy_gclient_config": {
+                "config": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "ci",
+          "builder": "mac-arm64-archive-dbg",
+          "project": "chromium"
+        }
+      ]
+    }
+  },
   "$build/goma": {
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org",
diff --git a/infra/config/generated/builders/ci/mac-official/properties.json b/infra/config/generated/builders/ci/mac-official/properties.json
index fa75a041..9acf9519c 100644
--- a/infra/config/generated/builders/ci/mac-official/properties.json
+++ b/infra/config/generated/builders/ci/mac-official/properties.json
@@ -1,4 +1,49 @@
 {
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "mac-official",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "builder_group": "chromium",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
+                "config": "chromium",
+                "target_bits": 64
+              },
+              "legacy_gclient_config": {
+                "apply_configs": [
+                  "checkout_pgo_profiles"
+                ],
+                "config": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "ci",
+          "builder": "mac-official",
+          "project": "chromium"
+        }
+      ],
+      "mirroring_builder_group_and_names": [
+        {
+          "builder": "mac-official",
+          "group": "tryserver.chromium"
+        }
+      ]
+    }
+  },
   "$build/goma": {
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org",
diff --git a/infra/config/generated/builders/ci/win10-code-coverage/properties.json b/infra/config/generated/builders/ci/win10-code-coverage/properties.json
index 573155d..736b789 100644
--- a/infra/config/generated/builders/ci/win10-code-coverage/properties.json
+++ b/infra/config/generated/builders/ci/win10-code-coverage/properties.json
@@ -6,11 +6,10 @@
     ],
     "use_clang_coverage": true
   },
-  "$build/goma": {
-    "enable_ats": true,
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org",
-    "use_luci_auth": true
+  "$build/reclient": {
+    "instance": "rbe-chromium-trusted",
+    "jobs": 250,
+    "metrics_project": "chromium-reclient-metrics"
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json
index d90599c..4f452e1e 100644
--- a/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json
@@ -1,4 +1,51 @@
 {
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "android-cronet-arm-dbg",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "build_gs_bucket": "chromium-android-archive",
+              "builder_group": "chromium.android",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_android_config": {
+                "config": "main_builder"
+              },
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "cronet_builder",
+                  "mb"
+                ],
+                "build_config": "Debug",
+                "config": "android",
+                "target_bits": 32,
+                "target_platform": "android"
+              },
+              "legacy_gclient_config": {
+                "apply_configs": [
+                  "android",
+                  "enable_reclient"
+                ],
+                "config": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "ci",
+          "builder": "android-cronet-arm-dbg",
+          "project": "chromium"
+        }
+      ]
+    }
+  },
   "$build/goma": {
     "enable_ats": true,
     "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/properties.json b/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/properties.json
index 4aada5e..b04aa47b 100644
--- a/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/properties.json
+++ b/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/properties.json
@@ -1,4 +1,50 @@
 {
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "chromeos-amd64-generic-dbg",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "build_gs_bucket": "chromium-chromiumos-archive",
+              "builder_group": "chromium.chromiumos",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
+                "build_config": "Debug",
+                "config": "chromium",
+                "target_arch": "intel",
+                "target_bits": 64,
+                "target_cros_boards": [
+                  "amd64-generic"
+                ],
+                "target_platform": "chromeos"
+              },
+              "legacy_gclient_config": {
+                "apply_configs": [
+                  "chromeos"
+                ],
+                "config": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "ci",
+          "builder": "chromeos-amd64-generic-dbg",
+          "project": "chromium"
+        }
+      ]
+    }
+  },
   "$build/goma": {
     "enable_ats": true,
     "rpc_extra_params": "?prod",
diff --git a/infra/config/generated/builders/try/mac-official/properties.json b/infra/config/generated/builders/try/mac-official/properties.json
index 4189f7f2..046f5307 100644
--- a/infra/config/generated/builders/try/mac-official/properties.json
+++ b/infra/config/generated/builders/try/mac-official/properties.json
@@ -1,4 +1,43 @@
 {
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "mac-official",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "builder_group": "chromium",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
+                "config": "chromium",
+                "target_bits": 64
+              },
+              "legacy_gclient_config": {
+                "apply_configs": [
+                  "checkout_pgo_profiles"
+                ],
+                "config": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "ci",
+          "builder": "mac-official",
+          "project": "chromium"
+        }
+      ]
+    }
+  },
   "$build/goma": {
     "rpc_extra_params": "?prod",
     "server_host": "goma.chromium.org",
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 40a12ada..ab6342d3 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -9198,11 +9198,10 @@
       }
       properties:
         '{'
-        '  "$build/goma": {'
-        '    "enable_ats": true,'
-        '    "rpc_extra_params": "?prod",'
-        '    "server_host": "goma.chromium.org",'
-        '    "use_luci_auth": true'
+        '  "$build/reclient": {'
+        '    "instance": "rbe-chromium-trusted",'
+        '    "jobs": 80,'
+        '    "metrics_project": "chromium-reclient-metrics"'
         '  },'
         '  "$recipe_engine/resultdb/test_presentation": {'
         '    "column_keys": [],'
@@ -21817,10 +21816,7 @@
         '  },'
         '  "builder_group": "chromium.android",'
         '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium",'
-        '  "sheriff_rotations": ['
-        '    "android"'
-        '  ]'
+        '  "recipe": "chromium"'
         '}'
       execution_timeout_secs: 10800
       build_numbers: YES
@@ -22057,10 +22053,7 @@
         '  },'
         '  "builder_group": "chromium.android",'
         '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium",'
-        '  "sheriff_rotations": ['
-        '    "android"'
-        '  ]'
+        '  "recipe": "chromium"'
         '}'
       execution_timeout_secs: 14400
       build_numbers: YES
@@ -55964,7 +55957,7 @@
         '{'
         '  "$build/binary_size": {'
         '    "analyze_targets": ['
-        '      "//fuchsia/release:fuchsia_sizes"'
+        '      "//tools/fuchsia/size_tests:fuchsia_sizes"'
         '    ],'
         '    "compile_targets": ['
         '      "fuchsia_sizes"'
diff --git a/infra/config/generated/sheriff-rotations/android.txt b/infra/config/generated/sheriff-rotations/android.txt
index 22135a6..662b1fd9 100644
--- a/infra/config/generated/sheriff-rotations/android.txt
+++ b/infra/config/generated/sheriff-rotations/android.txt
@@ -15,8 +15,6 @@
 ci/Marshmallow Tablet Tester
 ci/Nougat Phone Tester
 ci/android-10-arm64-rel
-ci/android-11-x86-rel
-ci/android-12-x64-rel
 ci/android-androidx-packager
 ci/android-arm64-proguard-rel
 ci/android-bfcache-rel
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.star b/infra/config/subprojects/chromium/ci/chromium.android.star
index d3f0f717..d6dd759f 100644
--- a/infra/config/subprojects/chromium/ci/chromium.android.star
+++ b/infra/config/subprojects/chromium/ci/chromium.android.star
@@ -619,6 +619,29 @@
 ci.builder(
     name = "android-cronet-arm-dbg",
     branch_selector = branches.STANDARD_MILESTONE,
+    builder_spec = builder_config.builder_spec(
+        gclient_config = builder_config.gclient_config(
+            config = "chromium",
+            apply_configs = [
+                "android",
+                "enable_reclient",
+            ],
+        ),
+        chromium_config = builder_config.chromium_config(
+            config = "android",
+            apply_configs = [
+                "cronet_builder",
+                "mb",
+            ],
+            build_config = builder_config.build_config.DEBUG,
+            target_bits = 32,
+            target_platform = builder_config.target_platform.ANDROID,
+        ),
+        android_config = builder_config.android_config(
+            config = "main_builder",
+        ),
+        build_gs_bucket = "chromium-android-archive",
+    ),
     console_view_entry = consoles.console_view_entry(
         category = "cronet|arm",
         short_name = "dbg",
@@ -907,6 +930,9 @@
         short_name = "11",
     ),
     tree_closing = True,
+    # TODO(crbug.com/1137474): Add it back to sheriff once the builder is more
+    # stable.
+    sheriff_rotations = args.ignore_default(None),
 )
 
 ci.builder(
@@ -916,6 +942,9 @@
         short_name = "12",
     ),
     execution_timeout = 4 * time.hour,
+    # TODO(crbug.com/1225851): Add it back to sheriff once the builder is more
+    # stable.
+    sheriff_rotations = args.ignore_default(None),
 )
 
 ci.thin_tester(
diff --git a/infra/config/subprojects/chromium/ci/chromium.chromiumos.star b/infra/config/subprojects/chromium/ci/chromium.chromiumos.star
index f884ece..07533413 100644
--- a/infra/config/subprojects/chromium/ci/chromium.chromiumos.star
+++ b/infra/config/subprojects/chromium/ci/chromium.chromiumos.star
@@ -253,6 +253,28 @@
 ci.builder(
     name = "chromeos-amd64-generic-dbg",
     branch_selector = branches.STANDARD_MILESTONE,
+    builder_spec = builder_config.builder_spec(
+        gclient_config = builder_config.gclient_config(
+            config = "chromium",
+            apply_configs = [
+                "chromeos",
+            ],
+        ),
+        chromium_config = builder_config.chromium_config(
+            config = "chromium",
+            apply_configs = [
+                "mb",
+            ],
+            build_config = builder_config.build_config.DEBUG,
+            target_arch = builder_config.target_arch.INTEL,
+            target_bits = 64,
+            target_cros_boards = [
+                "amd64-generic",
+            ],
+            target_platform = builder_config.target_platform.CHROMEOS,
+        ),
+        build_gs_bucket = "chromium-chromiumos-archive",
+    ),
     console_view_entry = consoles.console_view_entry(
         category = "simple|debug|x64",
         short_name = "dbg",
diff --git a/infra/config/subprojects/chromium/ci/chromium.fuzz.star b/infra/config/subprojects/chromium/ci/chromium.fuzz.star
index 22254fa..1848801 100644
--- a/infra/config/subprojects/chromium/ci/chromium.fuzz.star
+++ b/infra/config/subprojects/chromium/ci/chromium.fuzz.star
@@ -544,4 +544,7 @@
     triggering_policy = scheduler.greedy_batching(
         max_concurrent_invocations = 3,
     ),
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.LOW_JOBS_FOR_CI,
+    reclient_instance = rbe_instance.DEFAULT,
 )
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star
index bad91b54..872355b5 100644
--- a/infra/config/subprojects/chromium/ci/chromium.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -1188,6 +1188,9 @@
     os = os.WINDOWS_DEFAULT,
     coverage_test_types = ["overall", "unit"],
     use_clang_coverage = True,
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.DEFAULT,
+    reclient_instance = rbe_instance.DEFAULT,
 )
 
 fyi_ios_builder(
diff --git a/infra/config/subprojects/chromium/ci/chromium.star b/infra/config/subprojects/chromium/ci/chromium.star
index 076f32ab..4d4748a 100644
--- a/infra/config/subprojects/chromium/ci/chromium.star
+++ b/infra/config/subprojects/chromium/ci/chromium.star
@@ -421,6 +421,20 @@
 
 ci.builder(
     name = "mac-arm64-archive-dbg",
+    builder_spec = builder_config.builder_spec(
+        gclient_config = builder_config.gclient_config(
+            config = "chromium",
+        ),
+        chromium_config = builder_config.chromium_config(
+            config = "chromium",
+            apply_configs = [
+                "clobber",
+                "mb",
+            ],
+            build_config = builder_config.build_config.DEBUG,
+            target_bits = 64,
+        ),
+    ),
     console_view_entry = consoles.console_view_entry(
         category = "mac|arm",
         short_name = "dbg",
@@ -495,6 +509,21 @@
 ci.builder(
     name = "mac-official",
     branch_selector = branches.DESKTOP_EXTENDED_STABLE_MILESTONE,
+    builder_spec = builder_config.builder_spec(
+        gclient_config = builder_config.gclient_config(
+            config = "chromium",
+            apply_configs = [
+                "checkout_pgo_profiles",
+            ],
+        ),
+        chromium_config = builder_config.chromium_config(
+            config = "chromium",
+            apply_configs = [
+                "mb",
+            ],
+            target_bits = 64,
+        ),
+    ),
     builderless = False,
     console_view_entry = consoles.console_view_entry(
         category = "mac",
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
index e4f0cd1d..382fdf0 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
@@ -110,6 +110,9 @@
 try_.builder(
     name = "android-cronet-arm-dbg",
     branch_selector = branches.STANDARD_MILESTONE,
+    mirrors = [
+        "ci/android-cronet-arm-dbg",
+    ],
     main_list_view = "try",
     tryjob = try_.job(
         location_regexp = [
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star b/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star
index 3a9ef0d..8da163b 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star
@@ -38,6 +38,9 @@
 try_.builder(
     name = "chromeos-amd64-generic-dbg",
     branch_selector = branches.STANDARD_MILESTONE,
+    mirrors = [
+        "ci/chromeos-amd64-generic-dbg",
+    ],
     main_list_view = "try",
     tryjob = try_.job(
         location_regexp = [
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
index 67f423d..0455300 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -75,7 +75,7 @@
     properties = {
         "$build/binary_size": {
             "analyze_targets": [
-                "//fuchsia/release:fuchsia_sizes",
+                "//tools/fuchsia/size_tests:fuchsia_sizes",
             ],
             "compile_targets": [
                 "fuchsia_sizes",
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.star b/infra/config/subprojects/chromium/try/tryserver.chromium.star
index 3702ff9..b779c97 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.star
@@ -46,6 +46,9 @@
 try_.builder(
     name = "mac-official",
     branch_selector = branches.DESKTOP_EXTENDED_STABLE_MILESTONE,
+    mirrors = [
+        "ci/mac-official",
+    ],
     cores = None,
     # TODO(crbug.com/1279290) builds with PGO change take long time.
     # Keep in sync with mac-official in ci/chromium.star.
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 50cbaaaa..5e3f7d7 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -72,6 +72,7 @@
 #include "ios/chrome/browser/download/download_directory_util.h"
 #import "ios/chrome/browser/external_files/external_file_remover_factory.h"
 #import "ios/chrome/browser/external_files/external_file_remover_impl.h"
+#include "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h"
 #include "ios/chrome/browser/feature_engagement/tracker_factory.h"
 #import "ios/chrome/browser/first_run/first_run.h"
 #import "ios/chrome/browser/mailto_handler/mailto_handler_service.h"
@@ -131,6 +132,7 @@
 #import "ios/chrome/app/credential_provider_migrator_app_agent.h"
 #include "ios/chrome/browser/credential_provider/credential_provider_service_factory.h"
 #include "ios/chrome/browser/credential_provider/credential_provider_support.h"
+#import "ios/chrome/browser/credential_provider/credential_provider_util.h"
 #endif
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -187,6 +189,9 @@
 // Constants for deferred deletion of leftover session state files.
 NSString* const kPurgeWebSessionStates = @"PurgeWebSessionStates";
 
+// Constants for deferred favicons clean up.
+NSString* const kFaviconsCleanup = @"FaviconsCleanup";
+
 // Adapted from chrome/browser/ui/browser_init.cc.
 void RegisterComponentsForUpdate() {
   component_updater::ComponentUpdateService* cus =
@@ -1060,6 +1065,7 @@
   [self initializeMailtoHandling];
   [self scheduleSaveFieldTrialValuesForExtensions];
   [self scheduleEnterpriseManagedDeviceCheck];
+  [self scheduleFaviconsCleanup];
 }
 
 - (void)scheduleTasksRequiringBVCWithBrowserState {
@@ -1107,6 +1113,18 @@
                   }];
 }
 
+- (void)scheduleFaviconsCleanup {
+  [[DeferredInitializationRunner sharedInstance]
+      enqueueBlockNamed:kFaviconsCleanup
+                  block:^{
+#if BUILDFLAG(IOS_CREDENTIAL_PROVIDER_ENABLED)
+                    UpdateFaviconsStorage(
+                        IOSChromeFaviconLoaderFactory::GetForBrowserState(
+                            self.currentBrowserState));
+#endif
+                  }];
+}
+
 - (void)expireFirstUserActionRecorder {
   // Clear out any scheduled calls to this method. For example, the app may have
   // been backgrounded before the `kFirstUserActionTimeout` expired.
diff --git a/ios/chrome/browser/credential_provider/credential_provider_util.h b/ios/chrome/browser/credential_provider/credential_provider_util.h
index 4d109ef..285b120b 100644
--- a/ios/chrome/browser/credential_provider/credential_provider_util.h
+++ b/ios/chrome/browser/credential_provider/credential_provider_util.h
@@ -24,4 +24,7 @@
 // Returns the favicon file key.
 NSString* GetFaviconFileKey(const GURL& url);
 
+// Update favicons in the Chrome app group storage.
+void UpdateFaviconsStorage(FaviconLoader* favicon_loader);
+
 #endif  // IOS_CHROME_BROWSER_CREDENTIAL_PROVIDER_CREDENTIAL_PROVIDER_UTIL_H_
diff --git a/ios/chrome/browser/credential_provider/credential_provider_util.mm b/ios/chrome/browser/credential_provider/credential_provider_util.mm
index 376f0384..b48f86b 100644
--- a/ios/chrome/browser/credential_provider/credential_provider_util.mm
+++ b/ios/chrome/browser/credential_provider/credential_provider_util.mm
@@ -9,8 +9,13 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
+#include "components/password_manager/core/common/password_manager_features.h"
 #import "ios/chrome/browser/favicon/favicon_loader.h"
 #include "ios/chrome/common/app_group/app_group_constants.h"
+#import "ios/chrome/common/credential_provider/archivable_credential.h"
+#import "ios/chrome/common/credential_provider/archivable_credential_store.h"
+#import "ios/chrome/common/credential_provider/constants.h"
+#import "ios/chrome/common/credential_provider/credential.h"
 #import "ios/chrome/common/ui/favicon/favicon_attributes.h"
 #import "ios/chrome/common/ui/favicon/favicon_constants.h"
 #import "net/base/mac/url_conversions.h"
@@ -62,14 +67,13 @@
                         isDirectory:NO];
 
     // Create shared folder if it doesn't exist.
-    if (![[NSFileManager defaultManager]
-            fileExistsAtPath:[shared_favicon_attributes_folder_url path]]) {
-      [[NSFileManager defaultManager]
-                createDirectoryAtPath:[shared_favicon_attributes_folder_url
-                                          path]
-          withIntermediateDirectories:YES
-                           attributes:nil
-                                error:nil];
+    NSFileManager* file_manager = [NSFileManager defaultManager];
+    NSString* path = shared_favicon_attributes_folder_url.path;
+    if (![file_manager fileExistsAtPath:path]) {
+      [file_manager createDirectoryAtPath:path
+              withIntermediateDirectories:YES
+                               attributes:nil
+                                    error:nil];
     }
 
     // Write to file.
@@ -84,9 +88,118 @@
                               const GURL& site_url,
                               NSString* filename) {
   DCHECK(favicon_loader);
+  DCHECK(filename);
   favicon_loader->FaviconForPageUrl(
       site_url, kDesiredMediumFaviconSizePt, kMinFaviconSizePt,
       /*fallback_to_google_server=*/false, ^(FaviconAttributes* attributes) {
         SaveFaviconToSharedAppContainer(attributes, filename);
       });
 }
+
+// Clean up obsolete favicons from the Chrome app group storage.
+void CleanUpFavicons() {
+  // TODO(crbug.com/1300569): Remove this when kEnableFaviconForPasswords flag
+  // is removed.
+  NSFileManager* file_manager = [NSFileManager defaultManager];
+  NSString* path = app_group::SharedFaviconAttributesFolder().path;
+  if (!base::FeatureList::IsEnabled(
+          password_manager::features::kEnableFaviconForPasswords)) {
+    // Remove repo.
+    if ([file_manager fileExistsAtPath:path]) {
+      [file_manager removeItemAtPath:path error:nil];
+    }
+    return;
+  }
+
+  NSArray* filename_list = [file_manager contentsOfDirectoryAtPath:path
+                                                             error:nil];
+  if (!filename_list || [filename_list count] == 0) {
+    return;
+  }
+
+  ArchivableCredentialStore* archivable_store =
+      [[ArchivableCredentialStore alloc]
+          initWithFileURL:CredentialProviderSharedArchivableStoreURL()];
+  NSArray<id<Credential>>* all_credentials = archivable_store.credentials;
+  // Extract favicon filename from the credentials list.
+  NSMutableSet* credential_favicon_filename_set =
+      [[NSMutableSet alloc] initWithCapacity:all_credentials.count];
+  for (id<Credential> credential in all_credentials) {
+    if (credential.favicon) {
+      [credential_favicon_filename_set addObject:credential.favicon];
+    }
+  }
+
+  for (NSUInteger i = 0; i < [filename_list count]; i++) {
+    NSString* filename = [filename_list objectAtIndex:i];
+    if (![credential_favicon_filename_set containsObject:filename]) {
+      // Remove from storage.
+      NSURL* url = [app_group::SharedFaviconAttributesFolder()
+          URLByAppendingPathComponent:filename
+                          isDirectory:NO];
+      if ([file_manager fileExistsAtPath:[url path]]) {
+        [file_manager removeItemAtURL:url error:nil];
+      }
+    }
+  }
+}
+
+void CleanUpFaviconsInBackground() {
+  base::OnceCallback<void()> favicon_cleanup = base::BindOnce(^{
+    base::ScopedBlockingCall scoped_blocking_call(
+        FROM_HERE, base::BlockingType::WILL_BLOCK);
+    CleanUpFavicons();
+  });
+  base::ThreadPool::PostTask(
+      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+      std::move(favicon_cleanup));
+}
+
+void UpdateFaviconsStorage(FaviconLoader* favicon_loader) {
+  if (base::FeatureList::IsEnabled(
+          password_manager::features::kEnableFaviconForPasswords)) {
+    ArchivableCredentialStore* archivable_store =
+        [[ArchivableCredentialStore alloc]
+            initWithFileURL:CredentialProviderSharedArchivableStoreURL()];
+    NSArray<id<Credential>>* all_credentials = archivable_store.credentials;
+
+    for (id<Credential> credential : all_credentials) {
+      GURL url = GURL(base::SysNSStringToUTF8(credential.serviceIdentifier));
+      NSString* filename = credential.favicon;
+      if (!credential.favicon) {
+        // Add favicon name to the credential and update the store.
+        filename = GetFaviconFileKey(url);
+        ArchivableCredential* newCredential = [[ArchivableCredential alloc]
+                 initWithFavicon:filename
+              keychainIdentifier:credential.keychainIdentifier
+                            rank:credential.rank
+                recordIdentifier:credential.recordIdentifier
+               serviceIdentifier:credential.serviceIdentifier
+                     serviceName:credential.serviceName
+                            user:credential.user
+            validationIdentifier:credential.validationIdentifier];
+        if ([archivable_store
+                credentialWithRecordIdentifier:newCredential
+                                                   .recordIdentifier]) {
+          [archivable_store updateCredential:newCredential];
+        } else {
+          [archivable_store addCredential:newCredential];
+        }
+      }
+
+      // Fetch the favicon and save it to the app group storage.
+      if (filename) {
+        FetchFaviconForURLToPath(favicon_loader, url, filename);
+      }
+    }
+
+    // Save changes in the credential store and call the clean up method to
+    // remove obsolete favicons from the Chrome app group storage.
+    [archivable_store saveDataWithCompletion:^(NSError* error) {
+      CleanUpFaviconsInBackground();
+    }];
+  } else {
+    // Call clean up to remove the repo when the flag is off.
+    CleanUpFaviconsInBackground();
+  }
+}
diff --git a/ios/chrome/browser/ntp_tiles/BUILD.gn b/ios/chrome/browser/ntp_tiles/BUILD.gn
index 6663512..be8c2d6 100644
--- a/ios/chrome/browser/ntp_tiles/BUILD.gn
+++ b/ios/chrome/browser/ntp_tiles/BUILD.gn
@@ -40,6 +40,7 @@
   sources = [ "ntp_tiles_egtest.mm" ]
   deps = [
     "//base/test:test_support",
+    "//ios/chrome/browser/ui/content_suggestions:feature_flags",
     "//ios/chrome/test/earl_grey:eg_test_support+eg2",
     "//ios/testing/earl_grey:eg_test_support+eg2",
     "//ios/third_party/earl_grey2:test_lib",
diff --git a/ios/chrome/browser/ntp_tiles/ntp_tiles_egtest.mm b/ios/chrome/browser/ntp_tiles/ntp_tiles_egtest.mm
index 5a70ed1e..d7ab5d07 100644
--- a/ios/chrome/browser/ntp_tiles/ntp_tiles_egtest.mm
+++ b/ios/chrome/browser/ntp_tiles/ntp_tiles_egtest.mm
@@ -3,10 +3,12 @@
 // found in the LICENSE file.
 
 #import "base/test/ios/wait_util.h"
+#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/web_http_server_chrome_test_case.h"
+#import "ios/testing/earl_grey/app_launch_manager.h"
 #import "ios/testing/earl_grey/earl_grey_test.h"
 #import "ios/web/public/test/http_server/html_response_provider.h"
 #import "ios/web/public/test/http_server/html_response_provider_impl.h"
@@ -36,8 +38,19 @@
   [super tearDown];
 }
 
-// Tests that loading a URL ends up creating an NTP tile.
-- (void)testTopSitesTileAfterLoadURL {
+- (AppLaunchConfiguration)appConfigurationForTestCase {
+  AppLaunchConfiguration config;
+  config.relaunch_policy = ForceRelaunchByCleanShutdown;
+  config.features_enabled.push_back(kSingleCellContentSuggestions);
+  config.features_enabled.push_back(kContentSuggestionsHeaderMigration);
+  config.features_enabled.push_back(
+      kContentSuggestionsUIViewControllerMigration);
+  return config;
+}
+
+// Tests that loading a URL ends up creating an NTP tile and shows it on cold
+// start.
+- (void)testTopSitesTileAfterLoadURLAndColdStart {
   std::map<GURL, std::string> responses;
   GURL URL = web::test::HttpServer::MakeUrl("http://simple_tile.html");
   responses[URL] =
@@ -65,6 +78,12 @@
   [[EarlGrey selectElementWithMatcher:
                  chrome_test_util::StaticTextWithAccessibilityLabel(@"title1")]
       assertWithMatcher:grey_notNil()];
+
+  [[AppLaunchManager sharedManager]
+      ensureAppLaunchedWithConfiguration:self.appConfigurationForTestCase];
+  [[EarlGrey selectElementWithMatcher:
+                 chrome_test_util::StaticTextWithAccessibilityLabel(@"title1")]
+      assertWithMatcher:grey_notNil()];
 }
 
 // Tests that only one NTP tile is displayed for a TopSite that involves a
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
index 14d45f1..730405f 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
@@ -91,6 +91,7 @@
 }  // namespace
 
 @interface NewTabPageCoordinator () <AppStateObserver,
+                                     BooleanObserver,
                                      ContentSuggestionsHeaderCommands,
                                      DiscoverFeedDelegate,
                                      DiscoverFeedObserverBridgeDelegate,
@@ -267,6 +268,8 @@
   self.feedExpandedPref = [[PrefBackedBoolean alloc]
       initWithPrefService:_prefService
                  prefName:feed::prefs::kArticlesListVisible];
+  // Observer is necessary for multiwindow NTPs to remain in sync.
+  [self.feedExpandedPref setObserver:self];
 
   // Start observing DiscoverFeedService.
   _discoverFeedObserverBridge = std::make_unique<DiscoverFeedObserverBridge>(
@@ -391,6 +394,7 @@
     [omniboxCommandHandler cancelOmniboxEdit];
   }
 
+  [self.feedExpandedPref setObserver:nil];
   self.feedExpandedPref = nil;
 
   _prefChangeRegistrar.reset();
@@ -771,6 +775,12 @@
   [self updateVisible];
 }
 
+#pragma mark - BooleanObserver
+
+- (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
+  [self handleFeedVisibilityDidChange];
+}
+
 #pragma mark - DiscoverFeedDelegate
 
 - (void)contentSuggestionsWasUpdated {
@@ -1079,8 +1089,7 @@
 - (void)setFeedVisibleFromHeader:(BOOL)visible {
   [self.feedExpandedPref setValue:visible];
   [self.feedMetricsRecorder recordDiscoverFeedVisibilityChanged:visible];
-  [self updateNTPForFeed];
-  [self.feedHeaderViewController updateForFeedVisibilityChanged];
+  [self handleFeedVisibilityDidChange];
 }
 
 // Configures and returns the NTP mediator.
@@ -1139,6 +1148,13 @@
   [self.feedManagementCoordinator start];
 }
 
+// Handles how the NTP should react when the feed visbility preference is
+// changed.
+- (void)handleFeedVisibilityDidChange {
+  [self updateNTPForFeed];
+  [self.feedHeaderViewController updateForFeedVisibilityChanged];
+}
+
 #pragma mark - Getters
 
 - (FeedHeaderViewController*)feedHeaderViewController {
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index 76b919d..8e61eee 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-c5eea122cf09f54421b8f030739cb396c7b51c07
\ No newline at end of file
+03b7fa8ea2fbad81f2639121a81d65109b60d09b
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index eb522e3..c2d73fa5 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-06e3f8e8f0b830eae831fb51bd3377339206e1fe
\ No newline at end of file
+8f5fa7edad2c8a7b54e081a52f4d2fb7131fef47
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index 60c70502..17ef57e5 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-5cc161ecb09ebe34d1e66469bb513b1d4eedb891
\ No newline at end of file
+b3620d25e36c6e6c17f1a44122ea1cb20909f379
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index b3e23b85..28d20e5 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-abeccfc9d9c64c755053165ff1f8967193b4c871
\ No newline at end of file
+df674bc71debff95df8d19ac552ddbd182f46c32
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
index b861e585..80d4f23 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-b05f5532fa0281d82fa476cd5dc70e1a070b5461
\ No newline at end of file
+ab228fadeef1e16d3fa0c09d893a9406b9e36710
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
index c9637db..711c356 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-e901859f1ba20bcc781a114d3fdb4d8538344730
\ No newline at end of file
+3f38a0ea172cb5a790f556e66a7cf52afef68785
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 07c14e2..1ade71c6 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-d22a9ac6754c3fc9185b359b3a3aa835da751305
\ No newline at end of file
+43cebe3407a61ddeba9df4ed3e690352546dfa80
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index 7e74fd8..b8c5265d 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-86ba2ce57a9e44b4b4ecf834b5360996f0f51ecd
\ No newline at end of file
+14c49f8aba562f546d0070afac3515eccd116d5a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 17aabd7a..cf6844e 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-b15c93924637134c1cdee23e681303c6288f17bc
\ No newline at end of file
+bf4158a0ef22bc9516f51b438e0582c87d3f4e4a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index a7f3aff..90d053aa 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-f7af165ca8db4c7340d18988453d7f3c41a02880
\ No newline at end of file
+6da5d34e8be72fe45b1d2e237960a0002b102f94
\ No newline at end of file
diff --git a/ios/web/js_messaging/web_view_js_utils.mm b/ios/web/js_messaging/web_view_js_utils.mm
index 7eae772..85e96e5 100644
--- a/ios/web/js_messaging/web_view_js_utils.mm
+++ b/ios/web/js_messaging/web_view_js_utils.mm
@@ -65,7 +65,8 @@
       std::unique_ptr<base::Value> value =
           ValueResultFromWKResult(list_item, max_depth - 1);
       if (value) {
-        list->Append(std::move(value));
+        list->GetList().Append(
+            base::Value::FromUniquePtrValue(std::move(value)));
       }
     }
     result = std::move(list);
diff --git a/ios/web/public/js_messaging/optimize_js.gni b/ios/web/public/js_messaging/optimize_js.gni
index bbe1daf..cf23eb0 100644
--- a/ios/web/public/js_messaging/optimize_js.gni
+++ b/ios/web/public/js_messaging/optimize_js.gni
@@ -22,6 +22,14 @@
 #     referenced from within |primary_script|. Listing all these files here
 #     ensures this target is rebuilt if any of the files are changed.
 #
+#   output_name (optional):
+#     The name of the exported value or namespace. For more details, see
+#     https://rollupjs.org/guide/en/#outputname
+#
+#   deps (optional):
+#     The dependent targets which produce typescript compiler manifest files.
+#     These manifest files will be used to resolve script imports.
+
 template("optimize_js") {
   assert(defined(invoker.sources), "sources must be set")
   assert(defined(invoker.primary_script), "primary_script must be set")
@@ -35,7 +43,7 @@
     }
   }
   assert(_primary_script_found_in_sources,
-         "primnary_script must be listed in sources")
+         "primary_script must be listed in sources")
 
   optimize_target_name = target_name + "_optimize"
   _target_name = target_name
@@ -44,6 +52,7 @@
 
     forward_variables_from(invoker,
                            [
+                             "deps",
                              "sources",
                              "testonly",
                            ])
@@ -68,6 +77,22 @@
     if (!minify_scripts) {
       args += [ "--skip-minification" ]
     }
+
+    if (defined(invoker.output_name)) {
+      args += [
+        "--output-name",
+        invoker.output_name,
+      ]
+    }
+
+    if (defined(invoker.deps)) {
+      args += [ "--path-mapping-manifests" ]
+      foreach(_dep, invoker.deps) {
+        _dep_gen_dir =
+            rebase_path(get_label_info(_dep, "target_gen_dir"), root_build_dir)
+        args += [ "$_dep_gen_dir/tsconfig.manifest" ]
+      }
+    }
   }
 
   # copy the output file to the bundle data
diff --git a/ios/web/public/js_messaging/optimize_js.py b/ios/web/public/js_messaging/optimize_js.py
index af159ffb..583d36f 100755
--- a/ios/web/public/js_messaging/optimize_js.py
+++ b/ios/web/public/js_messaging/optimize_js.py
@@ -4,6 +4,7 @@
 # found in the LICENSE file.
 
 import argparse
+import json
 import os
 import shutil
 import sys
@@ -16,25 +17,48 @@
 import node
 import node_modules
 
-def create_rollup_config(config_out_file, rollup_root_dir):
+def create_rollup_config(config_out_file, rollup_root_dir, path_mappings):
   """Generates a rollup config file to configure and use the path resolver
   plugin which enforces import path format."""
   plugin_path = os.path.join(os.path.abspath(_HERE_PATH),
       'rollup_plugin_src_path_resolver.js')
 
+  path_mappings_json = json.dumps(path_mappings, separators=(',', ':'))
+
   config_content = f'''
       import src_path_resolver from '{plugin_path}';
       export default ({{
-        plugins: [ src_path_resolver('{rollup_root_dir}') ]
+        plugins: [
+          src_path_resolver('{rollup_root_dir}', '{path_mappings_json}')
+        ]
       }});
       '''
   with open(config_out_file, 'w') as f:
     f.write(config_content)
 
-def optimize_js(primary_script, js_out_file, skip_minification):
+def optimize_js(primary_script,
+    js_out_file,
+    path_mapping_manifests,
+    skip_minification,
+    output_name):
   """Creates a single output JavaScript file from |primary_script| (and any
-  imported scripts) and writes it out to |js_out_file|. The output script will
-  be minimized unless skip_minification is false."""
+  imported scripts) and writes it out to |js_out_file|. Script imports will be
+  resolved by searching for the script path in the maifest files passed to
+  |path_mapping_manifests| and using the directory location listed in the
+  manifest file to locate the source file.
+  The output script will be minimized unless |skip_minification| is false."""
+
+  path_mappings = {}
+  if path_mapping_manifests != None:
+    for manifest_path in path_mapping_manifests:
+      with open(manifest_path, 'r', encoding='utf-8') as manifest:
+        manifest_contents = json.load(manifest)
+        base_dir = manifest_contents['base_dir']
+        files = manifest_contents['files']
+
+        for f in files:
+          path_mappings[f] = os.path.abspath(os.path.join(base_dir, f))
+
   output_script_dir = os.path.dirname(js_out_file)
 
   os.makedirs(output_script_dir, exist_ok=True)
@@ -42,12 +66,14 @@
 
     rollup_config_file = \
         os.path.join(tmp_out_dir, 'rollup.config.js')
-    create_rollup_config(rollup_config_file, os.path.abspath(_SRC_PATH))
-
+    create_rollup_config(
+        rollup_config_file,
+        os.path.abspath(_SRC_PATH),
+        path_mappings)
     rollup_processed_file = \
         os.path.join(tmp_out_dir, os.path.basename(js_out_file))
 
-    node.RunNode([node_modules.PathToRollup(),
+    rollup_command = [node_modules.PathToRollup(),
         primary_script,
         '--format',
         'iife',
@@ -58,7 +84,12 @@
         '--file',
         rollup_processed_file,
         '--silent',
-    ])
+    ]
+
+    if output_name != None:
+      rollup_command += ['--name', output_name]
+
+    node.RunNode(rollup_command)
 
     with open(rollup_processed_file, 'r', encoding='utf-8') as f:
       output = f.read()
@@ -88,15 +119,27 @@
       required=True,
       help="Path to the output file for the compiled JavaScript to be written")
   parser.add_argument(
+      '--path-mapping-manifests',
+      required=False,
+      nargs='*',
+      default = None,
+      help="Path mapping manifest files to locate script imports.")
+  parser.add_argument(
       '--skip-minification',
       default=False,
       action='store_true')
+  parser.add_argument(
+      '--output-name',
+      required=False,
+      default = None,
+      help="The name for the exported symbols")
   args = parser.parse_args(argv)
 
   primary_script = os.path.abspath(args.primary_script)
   js_out_file = os.path.abspath(args.js_out_file)
 
-  optimize_js(primary_script, js_out_file, args.skip_minification)
+  optimize_js(primary_script, js_out_file,
+      args.path_mapping_manifests, args.skip_minification, args.output_name)
 
 if __name__ == '__main__':
   main(sys.argv[1:])
diff --git a/ios/web/public/js_messaging/rollup_plugin_src_path_resolver.js b/ios/web/public/js_messaging/rollup_plugin_src_path_resolver.js
index 526a0285..a96bdb0 100644
--- a/ios/web/public/js_messaging/rollup_plugin_src_path_resolver.js
+++ b/ios/web/public/js_messaging/rollup_plugin_src_path_resolver.js
@@ -8,19 +8,28 @@
 
 import path from 'path'
 
-export default function src_path_resolver(rootPath) {
+export default function src_path_resolver(rootPath, pathMappingsJson) {
   return {
     name: 'rollup-plugin-src-path-resolver',
 
     resolveId(source, originScript) {
-      // Allow root files to be processed by rollup.
+      // Allow root files to be processed directly by rollup.
       if (!originScript) {
         return null;
       }
 
       if (source.startsWith('//')) {
-        // Strip leading double slashes and combine path with root.
-        return path.join(rootPath, source.substr(2));
+        // Strip leading double slashes
+        const sourcePath = source.substr(2);
+
+        // Check if an import exists within a dependency directory.
+        const pathMappings = JSON.parse(pathMappingsJson);
+        if (sourcePath in pathMappings) {
+          return pathMappings[sourcePath]
+        }
+
+        // Assume file exists at root.
+        return path.join(rootPath, sourcePath);
       }
 
       // Relative paths are acceptable from within third-party scripts.
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller.mm b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
index 284367e33..0f800942 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_controller.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
@@ -520,7 +520,9 @@
                                   value:nsValue
                           userInitiated:userInitiated];
     }
-  } else if (params.type == "input") {
+  } else if (params.type == "input" || params.type == "keyup") {
+    // Some fields only emit 'keyup' events and not 'input' events, which would
+    // result in the delegate not being notified when the field is updated.
     if ([_delegate respondsToSelector:@selector
                    (autofillController:
                        didInputInFieldWithIdentifier:fieldType:formName:frameID
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm b/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm
index ab42113..d6cefa3b 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm
@@ -336,6 +336,32 @@
     [delegate verify];
 }
 
+// Tests CWVAutofillController delegate input callback is invoked by keyup
+// events.
+TEST_F(CWVAutofillControllerTest, InputCallbackFromKeyup) {
+  id delegate = OCMProtocolMock(@protocol(CWVAutofillControllerDelegate));
+  autofill_controller_.delegate = delegate;
+
+  [[delegate expect] autofillController:autofill_controller_
+          didInputInFieldWithIdentifier:kTestFieldIdentifier
+                              fieldType:@""
+                               formName:kTestFormName
+                                frameID:frame_id_
+                                  value:kTestFieldValue
+                          userInitiated:YES];
+
+  autofill::FormActivityParams params;
+  params.form_name = base::SysNSStringToUTF8(kTestFormName);
+  params.field_identifier = base::SysNSStringToUTF8(kTestFieldIdentifier);
+  params.value = base::SysNSStringToUTF8(kTestFieldValue);
+  params.frame_id = web::kMainFakeFrameId;
+  params.type = "keyup";
+  params.has_user_gesture = true;
+  auto frame = web::FakeWebFrame::CreateMainWebFrame(GURL::EmptyGURL());
+  form_activity_tab_helper_->FormActivityRegistered(frame.get(), params);
+  [delegate verify];
+}
+
 // Tests CWVAutofillController delegate blur callback is invoked.
 TEST_F(CWVAutofillControllerTest, BlurCallback) {
   id delegate = OCMProtocolMock(@protocol(CWVAutofillControllerDelegate));
diff --git a/ios/web_view/internal/passwords/web_view_password_manager_client.mm b/ios/web_view/internal/passwords/web_view_password_manager_client.mm
index cc11ad9..168d749 100644
--- a/ios/web_view/internal/passwords/web_view_password_manager_client.mm
+++ b/ios/web_view/internal/passwords/web_view_password_manager_client.mm
@@ -146,11 +146,11 @@
     std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,
     bool has_generated_password,
     bool is_update) {
-  NOTIMPLEMENTED();
+  // No op. We only show save dialogues after successful form submissions.
 }
 
 void WebViewPasswordManagerClient::HideManualFallbackForSaving() {
-  NOTIMPLEMENTED();
+  // No op. We only show save dialogues after successful form submissions.
 }
 
 void WebViewPasswordManagerClient::FocusedInputChanged(
diff --git a/ios/web_view/shell/shell_autofill_delegate.m b/ios/web_view/shell/shell_autofill_delegate.m
index 122a3c7..c8efd80 100644
--- a/ios/web_view/shell/shell_autofill_delegate.m
+++ b/ios/web_view/shell/shell_autofill_delegate.m
@@ -93,7 +93,18 @@
                           frameID:(NSString*)frameID
                             value:(NSString*)value
                     userInitiated:(BOOL)userInitiated {
-  // Not implemented.
+  // TODO(crbug.com/1323932): Fetching suggestions has an important side effect
+  // of calling PasswordFormManager::UpdateStateOnUserInput. This will ensure
+  // that the typed information can be remembered during the save dialogue.
+  // Make this method a no-op once the bug is fixed.
+  id completionHandler = ^(NSArray<CWVAutofillSuggestion*>* suggestions) {
+    NSLog(@"%@ suggestions: %@", NSStringFromSelector(_cmd), suggestions);
+  };
+  [autofillController fetchSuggestionsForFormWithName:formName
+                                      fieldIdentifier:fieldIdentifier
+                                            fieldType:fieldType
+                                              frameID:frameID
+                                    completionHandler:completionHandler];
 }
 
 - (void)autofillController:(CWVAutofillController*)autofillController
diff --git a/ios/web_view/shell/shell_view_controller.m b/ios/web_view/shell/shell_view_controller.m
index e13f5d9..3acd56e 100644
--- a/ios/web_view/shell/shell_view_controller.m
+++ b/ios/web_view/shell/shell_view_controller.m
@@ -168,7 +168,7 @@
                             forAxis:UILayoutConstraintAxisHorizontal];
   _field.delegate = self;
   _field.layer.cornerRadius = 2.0;
-  _field.keyboardType = UIKeyboardTypeURL;
+  _field.keyboardType = UIKeyboardTypeWebSearch;
   _field.autocapitalizationType = UITextAutocapitalizationTypeNone;
   _field.clearButtonMode = UITextFieldViewModeWhileEditing;
   _field.autocorrectionType = UITextAutocorrectionTypeNo;
diff --git a/remoting/host/pairing_registry_delegate_win.cc b/remoting/host/pairing_registry_delegate_win.cc
index 258ab4a..4258a65d 100644
--- a/remoting/host/pairing_registry_delegate_win.cc
+++ b/remoting/host/pairing_registry_delegate_win.cc
@@ -139,8 +139,10 @@
     }
 
     PairingRegistry::Pairing pairing = Load(base::WideToUTF8(value_name));
-    if (pairing.is_valid())
-      pairings->Append(pairing.ToValue());
+    if (pairing.is_valid()) {
+      pairings->GetList().Append(
+          base::Value::FromUniquePtrValue(pairing.ToValue()));
+    }
   }
 
   return pairings;
diff --git a/sandbox/win/src/sandbox_policy.h b/sandbox/win/src/sandbox_policy.h
index 6b34267..66ccda5 100644
--- a/sandbox/win/src/sandbox_policy.h
+++ b/sandbox/win/src/sandbox_policy.h
@@ -18,7 +18,10 @@
 
 class AppContainer;
 
-class TargetPolicy {
+// We need [[clang::lto_visibility_public]] because instances of this class are
+// passed across module boundaries. This means different modules must have
+// compatible definitions of the class even when LTO is enabled.
+class [[clang::lto_visibility_public]] TargetPolicy {
  public:
   // Windows subsystems that can have specific rules.
   // Note: The process subsystem(SUBSYS_PROCESS) does not evaluate the request
diff --git a/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc b/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc
index d1bd9ba..cfb4b552 100644
--- a/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc
+++ b/storage/browser/file_system/copy_or_move_operation_delegate_unittest.cc
@@ -629,7 +629,7 @@
  private:
   void GetUsageAndQuota(FileSystemType type, int64_t* usage, int64_t* quota) {
     blink::mojom::QuotaStatusCode status =
-        AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(), origin_,
+        AsyncFileTestHelper::GetUsageAndQuota(quota_manager_->proxy(), origin_,
                                               type, usage, quota);
     ASSERT_EQ(blink::mojom::QuotaStatusCode::kOk, status);
   }
diff --git a/storage/browser/file_system/file_system_operation_impl_unittest.cc b/storage/browser/file_system/file_system_operation_impl_unittest.cc
index b59b8511..ed25bd3 100644
--- a/storage/browser/file_system/file_system_operation_impl_unittest.cc
+++ b/storage/browser/file_system/file_system_operation_impl_unittest.cc
@@ -239,7 +239,8 @@
   void GetUsageAndQuota(int64_t* usage, int64_t* quota) {
     blink::mojom::QuotaStatusCode status =
         AsyncFileTestHelper::GetUsageAndQuota(
-            quota_manager_.get(), sandbox_file_system_.storage_key().origin(),
+            quota_manager_->proxy(),
+            sandbox_file_system_.storage_key().origin(),
             sandbox_file_system_.type(), usage, quota);
     task_environment_.RunUntilIdle();
     ASSERT_EQ(blink::mojom::QuotaStatusCode::kOk, status);
diff --git a/storage/browser/file_system/obfuscated_file_util_unittest.cc b/storage/browser/file_system/obfuscated_file_util_unittest.cc
index 19210c8..b44d65e 100644
--- a/storage/browser/file_system/obfuscated_file_util_unittest.cc
+++ b/storage/browser/file_system/obfuscated_file_util_unittest.cc
@@ -23,7 +23,11 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
+#include "base/task/thread_pool.h"
+#include "base/test/bind.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "components/services/filesystem/public/mojom/types.mojom.h"
@@ -49,6 +53,7 @@
 #include "storage/common/database/database_identifier.h"
 #include "storage/common/file_system/file_system_types.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
 #include "third_party/leveldatabase/leveldb_chrome.h"
 #include "url/gurl.h"
@@ -175,17 +180,25 @@
 
     storage_policy_ = base::MakeRefCounted<MockSpecialStoragePolicy>();
 
+    quota_manager_task_runner_ =
+        base::ThreadPool::CreateSingleThreadTaskRunner({base::MayBlock()});
+
     quota_manager_ = base::MakeRefCounted<QuotaManager>(
-        is_incognito(), data_dir_.GetPath(),
-        base::ThreadTaskRunnerHandle::Get(),
+        is_incognito(), data_dir_.GetPath(), quota_manager_task_runner_,
         /*quota_change_callback=*/base::DoNothing(), storage_policy_,
         GetQuotaSettingsFunc());
-    QuotaSettings settings;
-    settings.per_host_quota = 25 * 1024 * 1024;
-    settings.pool_size = settings.per_host_quota * 5;
-    settings.must_remain_available = 10 * 1024 * 1024;
-    settings.refresh_interval = base::TimeDelta::Max();
-    quota_manager_->SetQuotaSettings(settings);
+
+    quota_manager_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(
+                       [](const scoped_refptr<QuotaManager>& quota_manager) {
+                         QuotaSettings settings;
+                         settings.per_host_quota = 25 * 1024 * 1024;
+                         settings.pool_size = settings.per_host_quota * 5;
+                         settings.must_remain_available = 10 * 1024 * 1024;
+                         settings.refresh_interval = base::TimeDelta::Max();
+                         quota_manager->SetQuotaSettings(settings);
+                       },
+                       quota_manager_));
 
     // Every time we create a new sandbox_file_system helper,
     // it creates another context, which creates another path manager,
@@ -294,13 +307,20 @@
   void GetUsageFromQuotaManager() {
     int64_t quota = -1;
     quota_status_ = AsyncFileTestHelper::GetUsageAndQuota(
-        quota_manager_.get(), origin(), sandbox_file_system_.type(), &usage_,
+        quota_manager_->proxy(), origin(), sandbox_file_system_.type(), &usage_,
         &quota);
     EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, quota_status_);
   }
 
   void RevokeUsageCache() {
-    quota_manager_->ResetUsageTracker(sandbox_file_system_.storage_type());
+    quota_manager_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(
+                       [](const scoped_refptr<QuotaManager>& quota_manager,
+                          SandboxFileSystemTestHelper* sandbox_file_system) {
+                         quota_manager->ResetUsageTracker(
+                             sandbox_file_system->storage_type());
+                       },
+                       quota_manager_, &sandbox_file_system_));
     usage_cache()->Delete(sandbox_file_system_.GetUsageCachePath());
   }
 
@@ -804,6 +824,7 @@
   base::ScopedTempDir data_dir_;
   scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
   scoped_refptr<QuotaManager> quota_manager_;
+  scoped_refptr<base::SingleThreadTaskRunner> quota_manager_task_runner_;
   scoped_refptr<FileSystemContext> file_system_context_;
   blink::StorageKey storage_key_;
   FileSystemType type_;
diff --git a/storage/browser/quota/quota_manager_proxy.cc b/storage/browser/quota/quota_manager_proxy.cc
index 7a34e11..23b2c6d 100644
--- a/storage/browser/quota/quota_manager_proxy.cc
+++ b/storage/browser/quota/quota_manager_proxy.cc
@@ -147,16 +147,35 @@
   QuotaErrorOr<BucketInfo> bucket;
   base::WaitableEvent waiter(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                              base::WaitableEvent::InitialState::NOT_SIGNALED);
-  // Call the async GetOrCreateBucket but block until it completes.
-  GetOrCreateBucket(
-      params, quota_manager_impl_task_runner_,
+  // Asynchronously call GetOrCreateBucket and block until it completes.
+  quota_manager_impl_task_runner_->PostTask(
+      FROM_HERE,
       base::BindOnce(
-          [](base::WaitableEvent* waiter, QuotaErrorOr<BucketInfo>* sync_bucket,
-             QuotaErrorOr<BucketInfo> result_bucket) {
-            *sync_bucket = std::move(result_bucket);
-            waiter->Signal();
+          [](const scoped_refptr<QuotaManagerProxy>& self,
+             const BucketInitParams& params, base::WaitableEvent* waiter,
+             QuotaErrorOr<BucketInfo>* sync_bucket) {
+            DCHECK_CALLED_ON_VALID_SEQUENCE(
+                self->quota_manager_impl_sequence_checker_);
+            // If the database is still bootstrapping, return an error rather
+            // than risking deadlock.
+            if (!self->quota_manager_impl_ ||
+                self->quota_manager_impl_->is_bootstrapping_database_) {
+              *sync_bucket = QuotaError::kUnknownError;
+              waiter->Signal();
+              return;
+            }
+            // Otherwise, return the bucket value and resolve the waiter.
+            self->quota_manager_impl_->GetOrCreateBucket(
+                params, base::BindOnce(
+                            [](base::WaitableEvent* waiter,
+                               QuotaErrorOr<BucketInfo>* sync_bucket,
+                               QuotaErrorOr<BucketInfo> result_bucket) {
+                              *sync_bucket = std::move(result_bucket);
+                              waiter->Signal();
+                            },
+                            waiter, sync_bucket));
           },
-          &waiter, &bucket));
+          base::WrapRefCounted(this), params, &waiter, &bucket));
   waiter.Wait();
   return bucket;
 }
diff --git a/storage/browser/test/async_file_test_helper.cc b/storage/browser/test/async_file_test_helper.cc
index 5b94a94..0e5f40e 100644
--- a/storage/browser/test/async_file_test_helper.cc
+++ b/storage/browser/test/async_file_test_helper.cc
@@ -300,7 +300,7 @@
 }
 
 blink::mojom::QuotaStatusCode AsyncFileTestHelper::GetUsageAndQuota(
-    QuotaManager* quota_manager,
+    QuotaManagerProxy* quota_manager_proxy,
     const url::Origin& origin,
     FileSystemType type,
     int64_t* usage,
@@ -308,8 +308,9 @@
   blink::mojom::QuotaStatusCode status =
       blink::mojom::QuotaStatusCode::kUnknown;
   base::RunLoop run_loop;
-  quota_manager->GetUsageAndQuota(
+  quota_manager_proxy->GetUsageAndQuota(
       blink::StorageKey(origin), FileSystemTypeToQuotaStorageType(type),
+      base::SequencedTaskRunnerHandle::Get(),
       base::BindOnce(&DidGetUsageAndQuota, &status, usage, quota,
                      run_loop.QuitWhenIdleClosure()));
   run_loop.Run();
diff --git a/storage/browser/test/async_file_test_helper.h b/storage/browser/test/async_file_test_helper.h
index 67ab06a..ee600f6 100644
--- a/storage/browser/test/async_file_test_helper.h
+++ b/storage/browser/test/async_file_test_helper.h
@@ -15,7 +15,7 @@
 namespace storage {
 class FileSystemContext;
 class FileSystemURL;
-class QuotaManager;
+class QuotaManagerProxy;
 }
 
 namespace url {
@@ -120,7 +120,7 @@
   // Returns usage and quota. It's valid to pass nullptr to |usage| and/or
   // |quota|.
   static blink::mojom::QuotaStatusCode GetUsageAndQuota(
-      QuotaManager* quota_manager,
+      QuotaManagerProxy* quota_manager_proxy,
       const url::Origin& origin,
       FileSystemType type,
       int64_t* usage,
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 2c15ba7..4421d8d9 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -42,7 +42,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -121,7 +121,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -187,7 +187,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -253,7 +253,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -319,7 +319,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -385,7 +385,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -451,7 +451,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -517,7 +517,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -583,7 +583,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -656,7 +656,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -727,7 +727,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -795,7 +795,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -864,7 +864,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -933,7 +933,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1001,7 +1001,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1075,7 +1075,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1143,7 +1143,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1211,7 +1211,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1286,7 +1286,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1361,7 +1361,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1429,7 +1429,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1498,7 +1498,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1568,7 +1568,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1636,7 +1636,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1704,7 +1704,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1774,7 +1774,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1842,7 +1842,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1910,7 +1910,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -1978,7 +1978,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2046,7 +2046,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2114,7 +2114,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2183,7 +2183,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2251,7 +2251,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2319,7 +2319,7 @@
               "device_playstore_version": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2395,7 +2395,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2462,7 +2462,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2531,7 +2531,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2598,7 +2598,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2660,7 +2660,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2718,7 +2718,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2785,7 +2785,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2852,7 +2852,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2919,7 +2919,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -2987,7 +2987,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3055,7 +3055,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3122,7 +3122,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3189,7 +3189,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3257,7 +3257,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3324,7 +3324,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3391,7 +3391,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3464,7 +3464,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3531,7 +3531,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3605,7 +3605,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3681,7 +3681,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3754,7 +3754,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3821,7 +3821,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3888,7 +3888,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -3956,7 +3956,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4024,7 +4024,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4092,7 +4092,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4160,7 +4160,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4227,7 +4227,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4294,7 +4294,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4361,7 +4361,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4428,7 +4428,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4495,7 +4495,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4562,7 +4562,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4629,7 +4629,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4698,7 +4698,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4765,7 +4765,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4832,7 +4832,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4899,7 +4899,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -4966,7 +4966,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5033,7 +5033,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5100,7 +5100,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5167,7 +5167,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5234,7 +5234,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5301,7 +5301,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5368,7 +5368,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5435,7 +5435,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5502,7 +5502,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5569,7 +5569,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5636,7 +5636,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5703,7 +5703,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5771,7 +5771,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5838,7 +5838,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5905,7 +5905,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -5972,7 +5972,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6039,7 +6039,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6106,7 +6106,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6173,7 +6173,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6240,7 +6240,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6307,7 +6307,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6374,7 +6374,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6441,7 +6441,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6508,7 +6508,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6576,7 +6576,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6643,7 +6643,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6710,7 +6710,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6777,7 +6777,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6844,7 +6844,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6911,7 +6911,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -6978,7 +6978,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -7050,7 +7050,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -7118,7 +7118,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -7186,7 +7186,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -7253,7 +7253,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -7320,7 +7320,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -7387,7 +7387,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -7439,7 +7439,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -7492,7 +7492,7 @@
               "device_playstore_version": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -7548,7 +7548,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -7604,7 +7604,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -7656,7 +7656,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8033,7 +8033,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8117,7 +8117,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8202,7 +8202,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8287,7 +8287,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8372,7 +8372,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8457,7 +8457,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8542,7 +8542,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8627,7 +8627,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8712,7 +8712,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8797,7 +8797,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8882,7 +8882,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -8967,7 +8967,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9052,7 +9052,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9123,7 +9123,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9186,7 +9186,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9247,7 +9247,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9313,7 +9313,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9384,7 +9384,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9458,7 +9458,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9525,7 +9525,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9594,7 +9594,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9661,7 +9661,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9729,7 +9729,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -9799,7 +9799,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index cac95c7..2563101 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -10362,7 +10362,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -10429,7 +10429,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -10497,7 +10497,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -10563,7 +10563,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -10624,7 +10624,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -10682,7 +10682,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -10748,7 +10748,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -10814,7 +10814,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -10880,7 +10880,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -10948,7 +10948,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11015,7 +11015,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11081,7 +11081,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11147,7 +11147,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11214,7 +11214,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11280,7 +11280,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11347,7 +11347,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11413,7 +11413,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11490,7 +11490,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11566,7 +11566,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11638,7 +11638,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11704,7 +11704,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11772,7 +11772,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11841,7 +11841,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11910,7 +11910,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -11977,7 +11977,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12045,7 +12045,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12111,7 +12111,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12177,7 +12177,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12243,7 +12243,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12309,7 +12309,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12375,7 +12375,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12441,7 +12441,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12507,7 +12507,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12576,7 +12576,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12642,7 +12642,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12708,7 +12708,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12774,7 +12774,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12840,7 +12840,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12906,7 +12906,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -12972,7 +12972,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13038,7 +13038,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13104,7 +13104,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13171,7 +13171,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13237,7 +13237,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13303,7 +13303,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13369,7 +13369,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13435,7 +13435,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13501,7 +13501,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13568,7 +13568,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13635,7 +13635,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13702,7 +13702,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13768,7 +13768,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13834,7 +13834,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13900,7 +13900,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -13966,7 +13966,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14032,7 +14032,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14098,7 +14098,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14164,7 +14164,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14230,7 +14230,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14296,7 +14296,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14363,7 +14363,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14430,7 +14430,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14497,7 +14497,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14564,7 +14564,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14630,7 +14630,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14697,7 +14697,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14769,7 +14769,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14836,7 +14836,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14902,7 +14902,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -14972,7 +14972,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15039,7 +15039,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15107,7 +15107,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15174,7 +15174,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15235,7 +15235,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15294,7 +15294,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15360,7 +15360,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15426,7 +15426,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15492,7 +15492,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15560,7 +15560,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15627,7 +15627,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15693,7 +15693,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15759,7 +15759,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15826,7 +15826,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15892,7 +15892,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -15959,7 +15959,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16025,7 +16025,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16102,7 +16102,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16178,7 +16178,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16250,7 +16250,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16316,7 +16316,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16383,7 +16383,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16451,7 +16451,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16519,7 +16519,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16586,7 +16586,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16654,7 +16654,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16720,7 +16720,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16787,7 +16787,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16853,7 +16853,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16919,7 +16919,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -16985,7 +16985,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17051,7 +17051,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17117,7 +17117,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17186,7 +17186,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17253,7 +17253,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17319,7 +17319,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17385,7 +17385,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17451,7 +17451,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17517,7 +17517,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17583,7 +17583,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17649,7 +17649,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17715,7 +17715,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17782,7 +17782,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17848,7 +17848,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17914,7 +17914,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -17980,7 +17980,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18046,7 +18046,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18112,7 +18112,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18179,7 +18179,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18247,7 +18247,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18314,7 +18314,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18381,7 +18381,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18447,7 +18447,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18513,7 +18513,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18579,7 +18579,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18645,7 +18645,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18711,7 +18711,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18777,7 +18777,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18843,7 +18843,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18909,7 +18909,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -18975,7 +18975,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19042,7 +19042,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19108,7 +19108,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19175,7 +19175,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19241,7 +19241,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19307,7 +19307,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19374,7 +19374,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19440,7 +19440,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19507,7 +19507,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19579,7 +19579,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19646,7 +19646,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19712,7 +19712,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -19778,7 +19778,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -24710,7 +24710,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -24776,7 +24776,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -24842,7 +24842,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -24908,7 +24908,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -24974,7 +24974,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25040,7 +25040,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25107,7 +25107,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25178,7 +25178,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25244,7 +25244,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25310,7 +25310,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25376,7 +25376,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25442,7 +25442,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25508,7 +25508,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25575,7 +25575,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25646,7 +25646,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25712,7 +25712,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25778,7 +25778,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25844,7 +25844,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25910,7 +25910,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -25976,7 +25976,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26043,7 +26043,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26114,7 +26114,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26180,7 +26180,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26246,7 +26246,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26312,7 +26312,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26378,7 +26378,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26444,7 +26444,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26510,7 +26510,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26581,7 +26581,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26647,7 +26647,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26713,7 +26713,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26779,7 +26779,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26845,7 +26845,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26911,7 +26911,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -26978,7 +26978,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27049,7 +27049,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27115,7 +27115,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27181,7 +27181,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27247,7 +27247,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27313,7 +27313,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27379,7 +27379,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27446,7 +27446,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27577,7 +27577,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27643,7 +27643,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27709,7 +27709,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27775,7 +27775,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27841,7 +27841,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27907,7 +27907,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -27974,7 +27974,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -31832,7 +31832,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -31902,7 +31902,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -31970,7 +31970,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32038,7 +32038,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32106,7 +32106,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32174,7 +32174,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32247,7 +32247,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32314,7 +32314,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32381,7 +32381,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32456,7 +32456,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32530,7 +32530,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32597,7 +32597,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32666,7 +32666,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32735,7 +32735,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32802,7 +32802,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32869,7 +32869,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -32939,7 +32939,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33006,7 +33006,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33073,7 +33073,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33141,7 +33141,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33208,7 +33208,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33275,7 +33275,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33344,7 +33344,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33411,7 +33411,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33478,7 +33478,7 @@
               "device_playstore_version": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33552,7 +33552,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33613,7 +33613,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33670,7 +33670,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33736,7 +33736,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33802,7 +33802,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33868,7 +33868,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -33934,7 +33934,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34000,7 +34000,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34067,7 +34067,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34133,7 +34133,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34199,7 +34199,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34265,7 +34265,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34333,7 +34333,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34400,7 +34400,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34467,7 +34467,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34533,7 +34533,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34599,7 +34599,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34665,7 +34665,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34731,7 +34731,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34797,7 +34797,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34863,7 +34863,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34929,7 +34929,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -34995,7 +34995,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35061,7 +35061,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35127,7 +35127,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35193,7 +35193,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35260,7 +35260,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35326,7 +35326,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35392,7 +35392,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35459,7 +35459,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35526,7 +35526,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35592,7 +35592,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35658,7 +35658,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35724,7 +35724,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35790,7 +35790,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35856,7 +35856,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35922,7 +35922,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -35988,7 +35988,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -36054,7 +36054,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -36120,7 +36120,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -36186,7 +36186,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -36252,7 +36252,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -36318,7 +36318,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -36384,7 +36384,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41131,7 +41131,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41198,7 +41198,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41266,7 +41266,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41332,7 +41332,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41393,7 +41393,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41450,7 +41450,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41516,7 +41516,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41582,7 +41582,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41648,7 +41648,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41715,7 +41715,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41782,7 +41782,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41848,7 +41848,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41914,7 +41914,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -41981,7 +41981,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42047,7 +42047,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42114,7 +42114,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42180,7 +42180,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42246,7 +42246,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42320,7 +42320,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "e2-standard-8",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42396,7 +42396,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42468,7 +42468,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42534,7 +42534,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42600,7 +42600,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42668,7 +42668,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42736,7 +42736,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42803,7 +42803,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42870,7 +42870,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -42936,7 +42936,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43002,7 +43002,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43068,7 +43068,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43134,7 +43134,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43200,7 +43200,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43266,7 +43266,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43332,7 +43332,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43401,7 +43401,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43467,7 +43467,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43533,7 +43533,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43599,7 +43599,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43665,7 +43665,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43731,7 +43731,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43797,7 +43797,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43863,7 +43863,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43929,7 +43929,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -43995,7 +43995,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44061,7 +44061,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44127,7 +44127,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44193,7 +44193,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44259,7 +44259,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44325,7 +44325,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44392,7 +44392,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44460,7 +44460,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44526,7 +44526,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44592,7 +44592,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44658,7 +44658,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44724,7 +44724,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44790,7 +44790,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44856,7 +44856,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44922,7 +44922,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -44988,7 +44988,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45054,7 +45054,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45120,7 +45120,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45187,7 +45187,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45254,7 +45254,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45320,7 +45320,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45386,7 +45386,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45452,7 +45452,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45518,7 +45518,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45584,7 +45584,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45655,7 +45655,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45723,7 +45723,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45790,7 +45790,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45856,7 +45856,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -45922,7 +45922,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46007,7 +46007,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46091,7 +46091,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46176,7 +46176,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46261,7 +46261,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46346,7 +46346,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46431,7 +46431,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46516,7 +46516,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46601,7 +46601,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46686,7 +46686,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46771,7 +46771,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46856,7 +46856,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -46941,7 +46941,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47026,7 +47026,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47115,7 +47115,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47200,7 +47200,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47285,7 +47285,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47370,7 +47370,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47455,7 +47455,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47540,7 +47540,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47625,7 +47625,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47710,7 +47710,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47795,7 +47795,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47880,7 +47880,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -47965,7 +47965,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48050,7 +48050,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48123,7 +48123,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48207,7 +48207,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48292,7 +48292,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48377,7 +48377,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48462,7 +48462,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48547,7 +48547,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48632,7 +48632,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48717,7 +48717,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48802,7 +48802,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48887,7 +48887,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -48972,7 +48972,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49057,7 +49057,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49142,7 +49142,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49215,7 +49215,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49299,7 +49299,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49384,7 +49384,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49469,7 +49469,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49554,7 +49554,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49639,7 +49639,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49724,7 +49724,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49809,7 +49809,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49894,7 +49894,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -49979,7 +49979,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -50064,7 +50064,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -50149,7 +50149,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -50234,7 +50234,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
@@ -50311,7 +50311,7 @@
               "device_os": null,
               "device_type": null,
               "machine_type": "n1-standard-4|e2-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
+              "os": "Ubuntu-18.04",
               "pool": "chromium.tests.avd"
             }
           ],
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 47342395..b4e777b9 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5919,21 +5919,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5056.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5057.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5056.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5057.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5056.0",
-              "revision": "version:103.0.5056.0"
+              "location": "lacros_version_skew_tests_v103.0.5057.0",
+              "revision": "version:103.0.5057.0"
             }
           ],
           "dimension_sets": [
@@ -5945,7 +5945,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 103.0.5056.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5057.0"
       },
       {
         "args": [
@@ -6065,21 +6065,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5056.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5057.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5056.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5057.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5056.0",
-              "revision": "version:103.0.5056.0"
+              "location": "lacros_version_skew_tests_v103.0.5057.0",
+              "revision": "version:103.0.5057.0"
             }
           ],
           "dimension_sets": [
@@ -6091,7 +6091,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 103.0.5056.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5057.0"
       },
       {
         "isolate_profile_data": true,
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 3ad6a7d..817a3c0 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -11359,7 +11359,7 @@
       {
         "args": [
           "--sizes-path",
-          "fuchsia/release/size_tests/fyi_sizes_smoketest.json"
+          "tools/fuchsia/size_tests/fyi_sizes_smoketest.json"
         ],
         "isolate_name": "fuchsia_sizes",
         "merge": {
@@ -11377,7 +11377,7 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://fuchsia/release:fuchsia_sizes/"
+        "test_id_prefix": "ninja://tools/fuchsia/size_tests:fuchsia_sizes/"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 2535335..1eda38f 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -87922,28 +87922,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5056.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5057.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5056.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5057.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5056.0",
-              "revision": "version:103.0.5056.0"
+              "location": "lacros_version_skew_tests_v103.0.5057.0",
+              "revision": "version:103.0.5057.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 103.0.5056.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5057.0"
       },
       {
         "args": [
@@ -88043,28 +88043,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5056.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5057.0/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5056.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5057.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5056.0",
-              "revision": "version:103.0.5056.0"
+              "location": "lacros_version_skew_tests_v103.0.5057.0",
+              "revision": "version:103.0.5057.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 103.0.5056.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5057.0"
       },
       {
         "isolate_profile_data": true,
@@ -89439,20 +89439,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5056.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5057.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5056.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5057.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5056.0",
-              "revision": "version:103.0.5056.0"
+              "location": "lacros_version_skew_tests_v103.0.5057.0",
+              "revision": "version:103.0.5057.0"
             }
           ],
           "dimension_sets": [
@@ -89465,7 +89465,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 103.0.5056.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5057.0"
       },
       {
         "args": [
@@ -89585,20 +89585,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5056.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5057.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5056.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5057.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5056.0",
-              "revision": "version:103.0.5056.0"
+              "location": "lacros_version_skew_tests_v103.0.5057.0",
+              "revision": "version:103.0.5057.0"
             }
           ],
           "dimension_sets": [
@@ -89611,7 +89611,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 103.0.5056.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5057.0"
       },
       {
         "merge": {
@@ -91144,20 +91144,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5056.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5057.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5056.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5057.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5056.0",
-              "revision": "version:103.0.5056.0"
+              "location": "lacros_version_skew_tests_v103.0.5057.0",
+              "revision": "version:103.0.5057.0"
             }
           ],
           "dimension_sets": [
@@ -91170,7 +91170,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 103.0.5056.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5057.0"
       },
       {
         "args": [
@@ -91290,20 +91290,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5056.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5057.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5056.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5057.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5056.0",
-              "revision": "version:103.0.5056.0"
+              "location": "lacros_version_skew_tests_v103.0.5057.0",
+              "revision": "version:103.0.5057.0"
             }
           ],
           "dimension_sets": [
@@ -91316,7 +91316,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 103.0.5056.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5057.0"
       },
       {
         "merge": {
@@ -92051,20 +92051,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5056.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5057.0/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 103.0.5056.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 103.0.5057.0",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v103.0.5056.0",
-              "revision": "version:103.0.5056.0"
+              "location": "lacros_version_skew_tests_v103.0.5057.0",
+              "revision": "version:103.0.5057.0"
             }
           ],
           "dimension_sets": [
@@ -92077,7 +92077,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 103.0.5056.0"
+        "variant_id": "Lacros version skew testing ash 103.0.5057.0"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 2987ec2..3cad956 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -2980,7 +2980,7 @@
       {
         "args": [
           "--sizes-path",
-          "fuchsia/release/size_tests/fyi_sizes_smoketest.json"
+          "tools/fuchsia/size_tests/fyi_sizes_smoketest.json"
         ],
         "isolate_name": "fuchsia_sizes",
         "merge": {
@@ -2998,7 +2998,7 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://fuchsia/release:fuchsia_sizes/"
+        "test_id_prefix": "ninja://tools/fuchsia/size_tests:fuchsia_sizes/"
       }
     ]
   },
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 73a4e6b..74204a13 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -9927,7 +9927,8 @@
               "os": "Mac-11|Mac-10.16"
             }
           ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 4
         },
         "test": "sync_integration_tests",
         "test_id_prefix": "ninja://chrome/test:sync_integration_tests/"
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index ec2c54e1..90cdc50 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -863,7 +863,7 @@
     "type": "console_test_launcher",
   },
   "fuchsia_sizes": {
-    "label": "//fuchsia/release:fuchsia_sizes",
+    "label": "//tools/fuchsia/size_tests:fuchsia_sizes",
     "type": "generated_script",
   },
   "gcm_unit_tests": {
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index b9f5597..687d21f 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -646,6 +646,8 @@
       },
     },
   },
+  # TODO(crbug.com/1260217): Remove the xenial mixin once the MSAN bots have
+  # migrated to focal.
   'linux-xenial': {
     'swarming': {
       'dimensions': {
@@ -653,13 +655,6 @@
       },
     },
   },
-  'linux-xenial-or-bionic': {
-    'swarming': {
-      'dimensions': {
-        'os': 'Ubuntu-16.04|Ubuntu-18.04',
-      },
-    },
-  },
   'linux_amd_rx_5500_xt': {
     'swarming': {
       'dimensions': {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 63dfab6..e2ba137 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -2921,6 +2921,11 @@
       'Mac ASan 64 Tests (1)': {
         'swarming': {
           'shards': 3,
+          },
+      },
+      'Mac11 Tests': {
+        'swarming': {
+          'shards': 4,
         },
       },
       'ToTLinuxTSan': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 9fc517c..7e06ca68 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -1910,7 +1910,7 @@
         },
         'args': [
           '--sizes-path',
-          'fuchsia/release/size_tests/fyi_sizes_smoketest.json',
+          'tools/fuchsia/size_tests/fyi_sizes_smoketest.json',
         ],
       },
     },
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index b74fdd5..111a3af 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -22,15 +22,15 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5056.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5057.0/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 103.0.5056.0',
+    'identifier': 'Lacros version skew testing ash 103.0.5057.0',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v103.0.5056.0',
-          'revision': 'version:103.0.5056.0',
+          'location': 'lacros_version_skew_tests_v103.0.5057.0',
+          'revision': 'version:103.0.5057.0',
         },
       ],
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index a9c2d63..677c079f 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -718,7 +718,7 @@
           '11-x86-emulator',
           'emulator-4-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -731,7 +731,7 @@
           '12-x64-emulator',
           'emulator-8-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -858,7 +858,7 @@
           '10-x86-emulator',
           'emulator-4-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -871,7 +871,7 @@
           '11-x86-emulator',
           'emulator-4-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -884,7 +884,7 @@
           'lollipop-x86-emulator',
           'emulator-4-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -897,7 +897,7 @@
           'marshmallow-x86-emulator',
           'emulator-4-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -910,7 +910,7 @@
           'oreo-x86-emulator',
           'emulator-4-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -923,7 +923,7 @@
           'pie-x86-emulator',
           'emulator-4-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -952,7 +952,7 @@
           'kitkat-x86-emulator',
           'emulator-4-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -987,7 +987,7 @@
           'isolate_profile_data',
           'marshmallow-x86-emulator',
           'emulator-4-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1002,7 +1002,7 @@
           'has_native_resultdb_integration',
           'marshmallow-x86-emulator',
           'emulator-4-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1069,7 +1069,7 @@
           'has_native_resultdb_integration',
           'pie-x86-emulator',
           'emulator-4-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1083,7 +1083,7 @@
           'has_native_resultdb_integration',
           '10-x86-emulator',
           'emulator-4-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1096,7 +1096,7 @@
           'has_native_resultdb_integration',
           'marshmallow-x86-emulator',
           'emulator-4-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1109,7 +1109,7 @@
           'has_native_resultdb_integration',
           'oreo-x86-emulator',
           'emulator-4-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1122,7 +1122,7 @@
           'has_native_resultdb_integration',
           'pie-x86-emulator',
           'emulator-4-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1135,7 +1135,7 @@
           'has_native_resultdb_integration',
           '10-x86-emulator',
           'emulator-4-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1160,7 +1160,7 @@
           '12-x64-emulator',
           'emulator-8-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1179,7 +1179,7 @@
           'has_native_resultdb_integration',
           'pie-x86-emulator',
           'emulator-8-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'test_suites': {
@@ -1193,7 +1193,7 @@
           'marshmallow-x86-emulator',
           'emulator-4-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'additional_compile_targets': [
@@ -1214,7 +1214,7 @@
           'isolate_profile_data',
           'marshmallow-x86-emulator',
           'emulator-4-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
           'gtest_run_disabled',
         ],
@@ -1231,7 +1231,7 @@
           'isolate_profile_data',
           'nougat-x86-emulator',
           'emulator-4-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1259,7 +1259,7 @@
           'has_native_resultdb_integration',
           '11-x86-emulator',
           'emulator-4-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1272,7 +1272,7 @@
           'has_native_resultdb_integration',
           'pie-x86-emulator',
           'emulator-8-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'test_suites': {
@@ -1286,7 +1286,7 @@
           'has_native_resultdb_integration',
           'pie-x86-emulator',
           'emulator-8-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'test_suites': {
@@ -1300,7 +1300,7 @@
           '12-x64-emulator',
           'emulator-8-cores',
           'has_native_resultdb_integration',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'os_type': 'android',
@@ -1313,7 +1313,7 @@
           'has_native_resultdb_integration',
           'pie-x86-emulator',
           'emulator-8-cores',
-          'linux-xenial-or-bionic',
+          'linux-bionic',
           'x86-64',
         ],
         'test_suites': {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 69cb6104..210418e 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -4535,24 +4535,6 @@
             ]
         }
     ],
-    "LensAndroidIntentStudy": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "EnabledUseLensIntentStartActivity_20220418",
-                    "params": {
-                        "useLensIntentStartActivity": "true"
-                    },
-                    "enable_features": [
-                        "GoogleLensSdkIntent"
-                    ]
-                }
-            ]
-        }
-    ],
     "LightweightReactions": [
         {
             "platforms": [
@@ -4767,6 +4749,21 @@
             ]
         }
     ],
+    "MessagesPreinstall": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "MessagesPreinstall"
+                    ]
+                }
+            ]
+        }
+    ],
     "MetrickitCrashReport": [
         {
             "platforms": [
diff --git a/third_party/blink/renderer/core/frame/history.cc b/third_party/blink/renderer/core/frame/history.cc
index ff7bd1e..d52b383 100644
--- a/third_party/blink/renderer/core/frame/history.cc
+++ b/third_party/blink/renderer/core/frame/history.cc
@@ -166,18 +166,15 @@
   return state == StateInternal();
 }
 
-void History::back(ScriptState* script_state, ExceptionState& exception_state) {
-  go(script_state, -1, exception_state);
+void History::back(ExceptionState& exception_state) {
+  go(-1, exception_state);
 }
 
-void History::forward(ScriptState* script_state,
-                      ExceptionState& exception_state) {
-  go(script_state, 1, exception_state);
+void History::forward(ExceptionState& exception_state) {
+  go(1, exception_state);
 }
 
-void History::go(ScriptState* script_state,
-                 int delta,
-                 ExceptionState& exception_state) {
+void History::go(int delta, ExceptionState& exception_state) {
   if (!DomWindow()) {
     exception_state.ThrowSecurityError(
         "May not use a History object associated with a Document that is not "
@@ -185,10 +182,6 @@
     return;
   }
 
-  LocalDOMWindow* active_window = LocalDOMWindow::From(script_state);
-  // TODO(crbug.com/1309481): Remove this CHECK, and the `script_state`
-  // parameter altogether.
-  CHECK_EQ(DomWindow(), active_window);
   if (!DomWindow()->GetFrame()->IsNavigationAllowed())
     return;
 
diff --git a/third_party/blink/renderer/core/frame/history.h b/third_party/blink/renderer/core/frame/history.h
index e1091794..b9187f2 100644
--- a/third_party/blink/renderer/core/frame/history.h
+++ b/third_party/blink/renderer/core/frame/history.h
@@ -56,9 +56,9 @@
   unsigned length(ExceptionState&) const;
   ScriptValue state(ScriptState*, ExceptionState&);
 
-  void back(ScriptState*, ExceptionState&);
-  void forward(ScriptState*, ExceptionState&);
-  void go(ScriptState*, int delta, ExceptionState&);
+  void back(ExceptionState&);
+  void forward(ExceptionState&);
+  void go(int delta, ExceptionState&);
 
   void pushState(v8::Isolate* isolate,
                  const ScriptValue& data,
diff --git a/third_party/blink/renderer/core/frame/history.idl b/third_party/blink/renderer/core/frame/history.idl
index eee7797..01c956e6 100644
--- a/third_party/blink/renderer/core/frame/history.idl
+++ b/third_party/blink/renderer/core/frame/history.idl
@@ -33,9 +33,9 @@
     [HighEntropy=Direct, MeasureAs=HistoryLength, RaisesException] readonly attribute unsigned long length;
     [Measure, RaisesException] attribute ScrollRestoration scrollRestoration;
     [CallWith=ScriptState, RaisesException] readonly attribute any state;
-    [CallWith=ScriptState, RaisesException] void go(optional long delta = 0);
-    [CallWith=ScriptState, RaisesException] void back();
-    [CallWith=ScriptState, RaisesException] void forward();
+    [RaisesException] void go(optional long delta = 0);
+    [RaisesException] void back();
+    [RaisesException] void forward();
     [CallWith=Isolate, MeasureAs=HistoryPushState, RaisesException] void pushState(any data, DOMString title, optional DOMString? url = null);
     [CallWith=Isolate, MeasureAs=HistoryReplaceState, RaisesException] void replaceState(any data, DOMString title, optional DOMString? url = null);
 };
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
index 0ce9e2a..bb3bf2c6 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -1878,6 +1878,34 @@
   EXPECT_EQ(gfx::Vector2dF(2, 2), scale_node->local.To2dScale());
 }
 
+TEST_P(CompositingSimTest, UnifiedScrollWithMainThreadReasonsNeedsCommit) {
+  // This test requires scroll unification.
+  if (!RuntimeEnabledFeatures::ScrollUnificationEnabled())
+    return;
+
+  InitializeWithHTML(R"HTML(
+    <style>
+      body { height: 2500px; }
+      #h { background: url(data:image/png;base64,invalid) fixed; }
+    </style>
+    <div id="h">ABCDE</div>
+  )HTML");
+  Compositor().BeginFrame();
+  auto* layer_tree_host = Compositor().LayerTreeHost();
+  EXPECT_FALSE(layer_tree_host->CommitRequested());
+
+  // Simulate 100px scroll from compositor thread.
+  cc::CompositorCommitData commit_data;
+  commit_data.scrolls.emplace_back(
+      MainFrame().GetFrameView()->LayoutViewport()->GetScrollElementId(),
+      gfx::Vector2dF(0, 100.f), absl::nullopt);
+  layer_tree_host->ApplyCompositorChanges(&commit_data);
+
+  // Due to main thread scrolling reasons (fixed-background element), we need a
+  // commit to push the update to the transform tree.
+  EXPECT_TRUE(layer_tree_host->CommitRequested());
+}
+
 TEST_P(CompositingSimTest, FrameAttribution) {
   InitializeWithHTML(R"HTML(
     <div id='child' style='will-change: transform;'>test</div>
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
index f64d762..3413f5e 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -777,17 +777,11 @@
       GetSkColorInfo().alphaType(), shared_image_usage_flags,
       gpu::kNullSurfaceHandle);
 
-  auto* webgpu = WebGPUInterface();
-
   // Wait for the mailbox to be ready to be used.
   WaitSyncToken(shared_image_interface->GenUnverifiedSyncToken());
 
   // Ensure Dawn wire is initialized.
-  webgpu->RequestAdapterAsync(gpu::webgpu::PowerPreference::kHighPerformance,
-                              /*force_fallback_adapter*/ false,
-                              base::DoNothing());
-  WGPUDeviceProperties properties{};
-  webgpu->RequestDeviceAsync(0, properties, base::DoNothing());
+  WebGPUInterface()->DeprecatedEnsureDefaultDeviceSync();
 
   owning_thread_data().shared_image_mailbox = shared_image_mailbox;
 }
diff --git a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py
index c4c64c7e..2bd1da9 100644
--- a/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py
+++ b/third_party/blink/tools/blinkpy/web_tests/lint_test_expectations.py
@@ -405,7 +405,8 @@
     failures += f
     warnings += w
     failures.extend(check_virtual_test_suites(host, options))
-    failures.extend(check_smoke_tests(host, options))
+    # Disabled until crbug.com/1322981 is fixed.
+    #failures.extend(check_smoke_tests(host, options))
 
     if options.json:
         with open(options.json, 'w') as f:
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version
index 3739688..9da1f39 100644
--- a/third_party/blink/web_tests/external/Version
+++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@
-Version: f0d42096e3a2032b63924f2b53f4dac5a01250d7
+Version: da03d05625361b0d7d2e5185ae64efa79895d775
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 287c26df..5bb1168 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -126607,7 +126607,7 @@
        ]
       ],
       "image-orientation-background-properties-border-radius.html": [
-       "b7c80ff0f678b3d816fb122f085b12be3e81f8f2",
+       "d7ddabf966392e786fa21983a24a7d92631c34f3",
        [
         null,
         [
@@ -126622,12 +126622,12 @@
            null,
            [
             [
-             10,
-             10
+             0,
+             3
             ],
             [
-             100,
-             100
+             0,
+             331
             ]
            ]
           ]
@@ -126636,7 +126636,7 @@
        ]
       ],
       "image-orientation-background-properties.html": [
-       "732233949e5949a6b03458c7b54edc509ba6f482",
+       "9f80feb7e9aa2db4b5b126133ca88a363858cb74",
        [
         null,
         [
@@ -126651,12 +126651,12 @@
            null,
            [
             [
-             10,
-             10
+             0,
+             2
             ],
             [
-             100,
-             100
+             0,
+             313
             ]
            ]
           ]
@@ -127023,7 +127023,7 @@
        ]
       ],
       "image-orientation-mask-image.html": [
-       "dc9e5107b8eee82a6c446f9d6c173dbba5974311",
+       "7bae0cf4dc336cebd621b50b335d760ade6ee2bd",
        [
         null,
         [
@@ -127038,12 +127038,12 @@
            null,
            [
             [
-             1,
-             1
+             0,
+             2
             ],
             [
-             22,
-             22
+             0,
+             26
             ]
            ]
           ]
@@ -127081,7 +127081,7 @@
        ]
       ],
       "image-orientation-none-cross-origin-canvas.html": [
-       "d6123bee72c879c5971184eb672388b071cd313c",
+       "9753e9ab379bd8e3245ad960bb4c8a04fb556c6c",
        [
         null,
         [
@@ -127090,27 +127090,11 @@
           "=="
          ]
         ],
-        {
-         "fuzzy": [
-          [
-           null,
-           [
-            [
-             10,
-             10
-            ],
-            [
-             100,
-             100
-            ]
-           ]
-          ]
-         ]
-        }
+        {}
        ]
       ],
       "image-orientation-none-cross-origin-svg.html": [
-       "23e5cbfe9633677b07a0aa4e8dc18a3d0d0161a6",
+       "4fc9474edf2526974cd6381fd7b001a059c40f6e",
        [
         null,
         [
@@ -127119,27 +127103,11 @@
           "=="
          ]
         ],
-        {
-         "fuzzy": [
-          [
-           null,
-           [
-            [
-             10,
-             10
-            ],
-            [
-             100,
-             100
-            ]
-           ]
-          ]
-         ]
-        }
+        {}
        ]
       ],
       "image-orientation-none-cross-origin.html": [
-       "6629f78e5b2923a41e49b4236a4c8b7d17abb2f1",
+       "f36f899056aa5e073cff2b420da5b08c8d1cb3b1",
        [
         null,
         [
@@ -127148,23 +127116,7 @@
           "=="
          ]
         ],
-        {
-         "fuzzy": [
-          [
-           null,
-           [
-            [
-             10,
-             10
-            ],
-            [
-             100,
-             100
-            ]
-           ]
-          ]
-         ]
-        }
+        {}
        ]
       ],
       "image-orientation-none-image-document.html": [
@@ -127226,7 +127178,7 @@
        ]
       ],
       "svg-image-orientation-aspect-ratio.html": [
-       "ee053442d0d65ad48e0ee03cd7f08a4da5b8555e",
+       "d378dbfe546d0264e971157fa00b5938158d26c3",
        [
         null,
         [
@@ -127241,12 +127193,12 @@
            null,
            [
             [
-             10,
-             10
+             0,
+             3
             ],
             [
-             100,
-             100
+             0,
+             1432
             ]
            ]
           ]
@@ -148385,7 +148337,7 @@
       ]
      ],
      "backdrop-animate-002.html": [
-      "500fb403bd738d6ca77d3acac399cb7f9ab1398d",
+      "6fd153becdee39018031586d82186cd2bac67f11",
       [
        null,
        [
@@ -148400,11 +148352,11 @@
           null,
           [
            [
-            1,
+            0,
             1
            ],
            [
-            472272,
+            0,
             472272
            ]
           ]
@@ -148985,19 +148937,6 @@
        {}
       ]
      ],
-     "first-line-nested-gcs.html": [
-      "6777e5468f57b507f96f4e92fbba4393002d15e7",
-      [
-       null,
-       [
-        [
-         "/css/css-pseudo/first-line-green-ref.html",
-         "=="
-        ]
-       ],
-       {}
-      ]
-     ],
      "first-line-on-ancestor-block.html": [
       "6b797107df80156b511b9dc58c5ee40d6114cfc4",
       [
@@ -184570,7 +184509,7 @@
       ]
      ],
      "preserve3d-and-filter-with-perspective.html": [
-      "fde34a2d22eaab8976fab032a7c170da65837ed9",
+      "9d2d91df6e8935379b6ed390cfeba0e6f96bb5fe",
       [
        null,
        [
@@ -184585,11 +184524,11 @@
           null,
           [
            [
-            4,
+            0,
             4
            ],
            [
-            26,
+            0,
             26
            ]
           ]
@@ -189800,7 +189739,7 @@
       ]
      ],
      "transform-table-009.html": [
-      "00371fa507f3ee93a1d8b6a01e730692a13111a7",
+      "21aa044f8df26aba863fd39a0c0a85bea6ead0b2",
       [
        null,
        [
@@ -189819,11 +189758,11 @@
           null,
           [
            [
-            50,
+            0,
             50
            ],
            [
-            3,
+            0,
             3
            ]
           ]
@@ -189833,7 +189772,7 @@
       ]
      ],
      "transform-table-010.html": [
-      "89fae1716bd2ed3d33e32060f058fd5f48b408f0",
+      "8c660f87b52d1d2dfd33df2775f9fc7a282983d0",
       [
        null,
        [
@@ -189852,11 +189791,11 @@
           null,
           [
            [
-            50,
+            0,
             50
            ],
            [
-            3,
+            0,
             3
            ]
           ]
@@ -189866,7 +189805,7 @@
       ]
      ],
      "transform-table-011.html": [
-      "f2c8ca8a6140589bb9661e502042e0da340198a5",
+      "73a5c48dde8ab058275fd603cf5f4d571db4685a",
       [
        null,
        [
@@ -189885,11 +189824,11 @@
           null,
           [
            [
-            50,
+            0,
             50
            ],
            [
-            3,
+            0,
             3
            ]
           ]
@@ -227267,7 +227206,7 @@
    },
    "density-size-correction": {
     "density-corrected-image-svg-aspect-ratio-cross-origin.sub.html": [
-     "8c6512254503338919d55b66943fa1ea699b4471",
+     "4cedfd9aac3445312c8ee0fb8ca65cd8f562b30a",
      [
       null,
       [
@@ -227276,27 +227215,11 @@
         "=="
        ]
       ],
-      {
-       "fuzzy": [
-        [
-         null,
-         [
-          [
-           10,
-           10
-          ],
-          [
-           100,
-           100
-          ]
-         ]
-        ]
-       ]
-      }
+      {}
      ]
     ],
     "density-corrected-image-svg-aspect-ratio.html": [
-     "fbc68de65db86477eddae60bb122a6712123a574",
+     "2b4d938a14f5804048948c6a6999ea24b662915e",
      [
       null,
       [
@@ -227305,23 +227228,7 @@
         "=="
        ]
       ],
-      {
-       "fuzzy": [
-        [
-         null,
-         [
-          [
-           10,
-           10
-          ],
-          [
-           100,
-           100
-          ]
-         ]
-        ]
-       ]
-      }
+      {}
      ]
     ],
     "density-corrected-image-svg-cross-origin.sub.html": [
@@ -274255,11 +274162,11 @@
         []
        ],
        "image-orientation-none-cross-origin-canvas-ref.html": [
-        "1bd691075f0d29d3580e2103c3b30768f50f3031",
+        "c82f135a0913a46aca32ea014109c93780530359",
         []
        ],
        "image-orientation-none-cross-origin-ref.html": [
-        "3e6962184ec3dcb75cd08a440017ed84161fdb4a",
+        "0d6f9654b28f2cc679139e7732a5e4bb5410c8ed",
         []
        ],
        "image-orientation-none-cross-origin-svg-ref.html": [
@@ -278335,7 +278242,7 @@
       []
      ],
      "backdrop-animate-002-ref.html": [
-      "b020f0d17af22ac579c46e5360adc2ac80995dd3",
+      "b4f0ebd4b8072368a336942fe9cf24c6d56c6c4a",
       []
      ],
      "before-after-dynamic-custom-property-001-ref.html": [
@@ -278462,10 +278369,6 @@
       "84becd9a78d186ba3c0e658746fd56aef8039b74",
       []
      ],
-     "first-line-green-ref.html": [
-      "99e9c334bf2c856535c7643911a3050390658a6f",
-      []
-     ],
      "first-line-line-height-001-ref.html": [
       "13e9b20f34d44cbe436b6bbcbdd6e85884ee71ca",
       []
@@ -325939,6 +325842,10 @@
    "speculation-rules": {
     "prefetch": {
      "resources": {
+      "authenticate.py": [
+       "037a7c144e0ba6d14aec7e7108d161c049f46dd8",
+       []
+      ],
       "cookies.py": [
        "3c2299aa3a6787c6c6444fc1b58db1288ef710a4",
        []
@@ -325956,7 +325863,7 @@
        []
       ],
       "utils.sub.js": [
-       "8dba95cd1ca4c408d9f9fd79941676c64d4930ab",
+       "f9895add23087d4684a458f71f1ab7d119bcecb6",
        []
       ]
      }
@@ -418256,7 +418163,7 @@
        ]
       ],
       "scheme-blob.sub.any.js": [
-       "6e63cbecaa52c5d6ac5308101387afb4c5d6784b",
+       "eaf01ebdf296296e6e40b6d8757a426ccfc38207",
        [
         "fetch/api/basic/scheme-blob.sub.any.html",
         {
@@ -518890,6 +518797,21 @@
         "timeout": "long"
        }
       ]
+     ],
+     "user-pass.https.html": [
+      "94748f1eacffc22bf569f8e240bbf6a48be041e8",
+      [
+       "speculation-rules/prefetch/user-pass.https.html?cross-origin=false",
+       {
+        "timeout": "long"
+       }
+      ],
+      [
+       "speculation-rules/prefetch/user-pass.https.html?cross-origin=true",
+       {
+        "timeout": "long"
+       }
+      ]
      ]
     },
     "prerender": {
@@ -545732,7 +545654,7 @@
      ]
     ],
     "RTCPeerConnection-transport-stats.https.html": [
-     "2240bc40e92119c478700c024c0f9b64fcf1aa65",
+     "3dfba16c5643c5b4a8298e39f0cd39776fe5de23",
      [
       null,
       {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-background-properties-border-radius.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-background-properties-border-radius.html
index b7c80ff0..d7ddabf 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-background-properties-border-radius.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-background-properties-border-radius.html
@@ -6,7 +6,7 @@
 <link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
 <link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
 <link rel="match" href="reference/image-orientation-background-properties-border-radius-ref.html">
-<meta name=fuzzy content="10;100">
+<meta name=fuzzy content="0-3;0-331">
 <style>
     div {
         position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-background-properties.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-background-properties.html
index 732233949..9f80feb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-background-properties.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-background-properties.html
@@ -6,7 +6,7 @@
 <link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
 <link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
 <link rel="match" href="reference/image-orientation-background-properties-ref.html">
-<meta name=fuzzy content="10;100">
+<meta name=fuzzy content="0-2;0-313">
 <style>
     div {
         position: absolute;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-mask-image.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-mask-image.html
index dc9e510..7bae0cf 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-mask-image.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-mask-image.html
@@ -4,7 +4,7 @@
 <link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au">
 <link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
 <link rel="match" href="reference/image-orientation-mask-image-ref.html">
-<meta name=fuzzy content="1;22">
+<meta name=fuzzy content="0-2;0-26">
 <style>
 div {
   width: 100px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-canvas.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-canvas.html
index d6123be..9753e9a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-canvas.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-canvas.html
@@ -7,7 +7,6 @@
 <link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org">
 <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5165">
 <link rel="match" href="reference/image-orientation-none-cross-origin-canvas-ref.html">
-<meta name=fuzzy content="10;100">
 <style>
     img {display: none}
     canvas {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-svg.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-svg.html
index 23e5cbf..4fc9474 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-svg.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin-svg.html
@@ -6,7 +6,6 @@
 <link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
 <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5165">
 <link rel="match" href="reference/image-orientation-none-cross-origin-svg-ref.html">
-<meta name=fuzzy content="10;100">
 <script src="/common/get-host-info.sub.js"></script>
 <script src="/common/reftest-wait.js"></script>
 <script src="/common/rendering-utils.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin.html
index 6629f78..f36f899 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/image-orientation-none-cross-origin.html
@@ -7,7 +7,6 @@
 <link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org">
 <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5165">
 <link rel="match" href="reference/image-orientation-none-cross-origin-ref.html">
-<meta name=fuzzy content="10;100">
 <style>
     body {
         overflow: hidden;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-canvas-ref.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-canvas-ref.html
index 1bd6910..c82f135 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-canvas-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-canvas-ref.html
@@ -5,7 +5,6 @@
 <title>CSS Images Module Level 3: image-orientation: none</title>
 <link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org">
 <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5165">
-<meta name=fuzzy content="10;100">
 <style>
     body {
         overflow: hidden;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-ref.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-ref.html
index 3e69621..0d6f9654 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/reference/image-orientation-none-cross-origin-ref.html
@@ -4,7 +4,6 @@
 <meta charset="utf-8">
 <link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org">
 <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5165">
-<meta name=fuzzy content="10;100">
 <style>
     body {
         overflow: hidden;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/svg-image-orientation-aspect-ratio.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/svg-image-orientation-aspect-ratio.html
index ee05344..d378dbfe 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/svg-image-orientation-aspect-ratio.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-orientation/svg-image-orientation-aspect-ratio.html
@@ -6,7 +6,7 @@
 <link rel="author" title="Stephen Chenney" href="mailto:schenney@chromium.org">
 <link rel="help" href="https://drafts.csswg.org/css-images-3/#propdef-image-orientation">
 <link rel="match" href="reference/svg-image-orientation-aspect-ratio-ref.html">
-<meta name=fuzzy content="10;100">
+<meta name=fuzzy content="0-3;0-1432">
 </head>
 <body style="margin:0">
     <svg style="width: 600px; height: 600px">
@@ -23,4 +23,4 @@
         <image xlink:href="support/exif-orientation-8-llo.jpg" x="200" y="450" width="150" height="150" preserveAspectRatio="none"></image>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/backdrop-animate-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/backdrop-animate-002-ref.html
index b020f0d..b4f0ebd 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/backdrop-animate-002-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/backdrop-animate-002-ref.html
@@ -5,7 +5,6 @@
 #target::backdrop {
   opacity: 0.1;
   background-color: green;
-  will-change: transform;
 }
 </style>
 <script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/backdrop-animate-002.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/backdrop-animate-002.html
index 500fb403..6fd153b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/backdrop-animate-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/backdrop-animate-002.html
@@ -1,18 +1,11 @@
 <!DOCTYPE html>
-<html class="reftest-wait">
 <meta charset="utf-8">
 <title>CSS Test: A Web Animations on ::backdrop</title>
 <link rel="help" href="https://fullscreen.spec.whatwg.org/#::backdrop-pseudo-element">
 <link rel="match" href="backdrop-animate-002-ref.html">
 <dialog id="target">Dialog contents</dialog>
-<!-- This test fails on WPT.fyi with off-by-one on the green background: -->
-<meta name=fuzzy content="maxDifference=1;totalPixels=472272">
-
-<style>
-#target::backdrop {
-  will-change: transform;
-}
-</style>
+<!-- This test fails on WPT.fyi with off-by-one on the green background (Chrome-only): -->
+<meta name="fuzzy" content="maxDifference=0-1;totalPixels=0-472272">
 <script>
 const target = document.getElementById("target");
 target.showModal();
@@ -23,9 +16,4 @@
   pseudoElement: "::backdrop",
   duration: Infinity
 });
-requestAnimationFrame(() => {
-  requestAnimationFrame(() => {
-    document.documentElement.classList.remove("reftest-wait");
-  });
-});
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-filter-with-perspective.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-filter-with-perspective.html
index fde34a2..9d2d91d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-filter-with-perspective.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-filter-with-perspective.html
@@ -6,7 +6,7 @@
 <link rel="help" href="https://drafts.fxtf.org/filter-effects/#FilterProperty">
 <meta name="assert" content="The filtered element is rendered correctly without clipping, despite the interesting transform.">
 <link rel="match" href="preserve3d-and-filter-with-perspective-ref.html">
-<meta name="fuzzy" content="maxDifference=4;totalPixels=26">
+<meta name="fuzzy" content="maxDifference=0-4;totalPixels=0-26">
 
 
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-009.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-009.html
index 00371fa5..21aa044 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-009.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-009.html
@@ -9,7 +9,7 @@
     &lt;tbody&gt;, so nothing should vanish.">
     <link rel="match" href="transform-table-009-ref.html">
     <link rel="mismatch" href="transform-table-009-notref.html">
-    <meta name="fuzzy" content="maxDifference=50;totalPixels=3">
+    <meta name="fuzzy" content="maxDifference=0-50;totalPixels=0-3">
     <style>
       table, tbody, tr, td {
         margin: 0;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-010.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-010.html
index 89fae171..8c660f8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-010.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-010.html
@@ -11,7 +11,7 @@
     display (mirrored).">
     <link rel="match" href="transform-table-009-ref.html">
     <link rel="mismatch" href="transform-table-010-notref.html">
-    <meta name="fuzzy" content="maxDifference=50;totalPixels=3">
+    <meta name="fuzzy" content="maxDifference=0-50;totalPixels=0-3">
     <style>
       body > div {
         transform: rotateX(90deg);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-011.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-011.html
index f2c8ca8..73a5c48 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-011.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-table-011.html
@@ -11,7 +11,7 @@
     preserve-3d specified, so the text should not vanish.">
     <link rel="match" href="transform-table-009-ref.html">
     <link rel="mismatch" href="transform-table-011-notref.html">
-    <meta name="fuzzy" content="maxDifference=50;totalPixels=3">
+    <meta name="fuzzy" content="maxDifference=0-50;totalPixels=0-3">
     <style>
       body > div {
         transform: rotateX(90deg);
diff --git a/third_party/blink/web_tests/external/wpt/density-size-correction/density-corrected-image-svg-aspect-ratio-cross-origin.sub.html b/third_party/blink/web_tests/external/wpt/density-size-correction/density-corrected-image-svg-aspect-ratio-cross-origin.sub.html
index 8c651225..4cedfd9a 100644
--- a/third_party/blink/web_tests/external/wpt/density-size-correction/density-corrected-image-svg-aspect-ratio-cross-origin.sub.html
+++ b/third_party/blink/web_tests/external/wpt/density-size-correction/density-corrected-image-svg-aspect-ratio-cross-origin.sub.html
@@ -3,7 +3,6 @@
     <title>Density Corrected Size: SVG aspect ratio (cross-origin)</title>
     <link rel="match" href="density-corrected-image-svg-aspect-ratio-ref.html" />
     <meta name="assert" content="Assert that SVG aspect ratio is applied correctly on density-corrected images">
-    <meta name=fuzzy content="10;100">
   </head>
   <body>
     <svg style="width: 800px; height: 800px">
diff --git a/third_party/blink/web_tests/external/wpt/density-size-correction/density-corrected-image-svg-aspect-ratio.html b/third_party/blink/web_tests/external/wpt/density-size-correction/density-corrected-image-svg-aspect-ratio.html
index fbc68de..2b4d938a 100644
--- a/third_party/blink/web_tests/external/wpt/density-size-correction/density-corrected-image-svg-aspect-ratio.html
+++ b/third_party/blink/web_tests/external/wpt/density-size-correction/density-corrected-image-svg-aspect-ratio.html
@@ -4,7 +4,6 @@
     <link rel="author" title="Noam Rosenthal" href="noam@webkit.org">
     <link rel="match" href="density-corrected-image-svg-aspect-ratio-ref.html" />
     <meta name="assert" content="Assert that SVG aspect ratio is applied correctly on density-corrected images">
-    <meta name=fuzzy content="10;100">
   </head>
   <body>
     <svg style="width: 800px; height: 800px">
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/basic/scheme-blob.sub.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/basic/scheme-blob.sub.any.js
index 6e63cbec..eaf01eb 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/api/basic/scheme-blob.sub.any.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/basic/scheme-blob.sub.any.js
@@ -42,4 +42,7 @@
   checkKoUrl(URL.createObjectURL(blob2), method, "Fetching [" + method + "] URL.createObjectURL(blob) is KO");
 });
 
+checkKoUrl("blob:not-backed-by-a-blob/", "GET",
+           "Fetching [GET] blob:not-backed-by-a-blob/ is KO");
+
 done();
diff --git a/third_party/libusb/README.chromium b/third_party/libusb/README.chromium
index 071a981..8fc6c2c 100644
--- a/third_party/libusb/README.chromium
+++ b/third_party/libusb/README.chromium
@@ -24,3 +24,7 @@
 - open-fd.patch has been applied.
 - Added libusb_get_raw_config_descriptor and libusb_get_active_config_value
   methods to avoid using the built-in parser.
+- Removed OSAtomic calls from darwin_usb.c for macOS compatibility by
+  backporting and simplifying the 10.12 branch of the upstream
+  https://android.googlesource.com/platform/external/libusb/+/1e05092aa98d60c717929629ac16590595e08431
+  as the 10.12 branch works fine on all previous OSes.
diff --git a/third_party/libusb/src/libusb/os/darwin_usb.c b/third_party/libusb/src/libusb/os/darwin_usb.c
index f6b397e..6ecc1eb 100644
--- a/third_party/libusb/src/libusb/os/darwin_usb.c
+++ b/third_party/libusb/src/libusb/os/darwin_usb.c
@@ -22,13 +22,13 @@
 #include <ctype.h>
 #include <errno.h>
 #include <pthread.h>
+#include <stdatomic.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <libkern/OSAtomic.h>
 
 #include <mach/clock.h>
 #include <mach/clock_types.h>
@@ -50,7 +50,7 @@
 static clock_serv_t clock_monotonic;
 
 static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
-static volatile int32_t initCount = 0;
+_Atomic int32_t initCount = ATOMIC_VAR_INIT(0);
 
 static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER;
 static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices};
@@ -418,7 +418,7 @@
     return rc;
   }
 
-  if (OSAtomicIncrement32Barrier(&initCount) == 1) {
+  if (atomic_fetch_add(&initCount, 1) == 0) {
     /* create the clocks that will be used */
 
     if (!initted) {
@@ -443,7 +443,7 @@
 }
 
 static void darwin_exit (void) {
-  if (OSAtomicDecrement32Barrier(&initCount) == 0) {
+  if (atomic_fetch_sub(&initCount, 1) == 1) {
     mach_port_deallocate(mach_task_self(), clock_realtime);
     mach_port_deallocate(mach_task_self(), clock_monotonic);
 
diff --git a/tools/android/checkxmlstyle/checkxmlstyle.py b/tools/android/checkxmlstyle/checkxmlstyle.py
index 84ed9704..c8b46a52 100644
--- a/tools/android/checkxmlstyle/checkxmlstyle.py
+++ b/tools/android/checkxmlstyle/checkxmlstyle.py
@@ -54,6 +54,8 @@
 
     self._color_set_or_none = set()
     for color_dir in helpers.COLOR_STATE_LIST_DIRS:
+      if not os.path.isdir(color_dir):
+        continue
       for color_file in os.listdir(color_dir):
         if '.' in color_file:
           self._color_set_or_none.add(color_file[:color_file.index('.')])
diff --git a/tools/android/checkxmlstyle/helpers.py b/tools/android/checkxmlstyle/helpers.py
index ff39c2b..0055838 100644
--- a/tools/android/checkxmlstyle/helpers.py
+++ b/tools/android/checkxmlstyle/helpers.py
@@ -41,7 +41,6 @@
     # Generated with the command below. When color state lists in new folders
     # are added, re-run this command and update.
     # find chrome/ components/ -name *\.xml | grep "/res/color" | xargs grep "<selector" | cut -d: -f1 | xargs dirname | sort | uniq | sed "s/^/'/" | sed "s/$/\/',/"
-    'chrome/android/java/res/color/',
     'chrome/browser/feed/android/java/res/color/',
     'components/browser_ui/styles/android/java/res/color/',
     'components/browser_ui/styles/android/java/res/color-night/',
diff --git a/fuchsia/release/BUILD.gn b/tools/fuchsia/size_tests/BUILD.gn
similarity index 100%
rename from fuchsia/release/BUILD.gn
rename to tools/fuchsia/size_tests/BUILD.gn
diff --git a/fuchsia/release/size_tests/fyi_sizes.json b/tools/fuchsia/size_tests/fyi_sizes.json
similarity index 100%
rename from fuchsia/release/size_tests/fyi_sizes.json
rename to tools/fuchsia/size_tests/fyi_sizes.json
diff --git a/fuchsia/release/size_tests/fyi_sizes_smoketest.json b/tools/fuchsia/size_tests/fyi_sizes_smoketest.json
similarity index 100%
rename from fuchsia/release/size_tests/fyi_sizes_smoketest.json
rename to tools/fuchsia/size_tests/fyi_sizes_smoketest.json
diff --git a/fuchsia/release/size_tests/fyi_sizes_warning.json b/tools/fuchsia/size_tests/fyi_sizes_warning.json
similarity index 100%
rename from fuchsia/release/size_tests/fyi_sizes_warning.json
rename to tools/fuchsia/size_tests/fyi_sizes_warning.json
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 43a2900..dfb9f52 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -292,7 +292,7 @@
       'Libfuzzer Upload Linux32 V8-ARM ASan': 'libfuzzer_asan_release_bot_x86_v8_arm_reclient',
       'Libfuzzer Upload Linux32 V8-ARM ASan Debug': 'libfuzzer_asan_debug_bot_x86_v8_arm_reclient',
       'Libfuzzer Upload Mac ASan': 'libfuzzer_mac_asan_shared_release_bot',
-      'Libfuzzer Upload Windows ASan': 'libfuzzer_windows_asan_release_bot',
+      'Libfuzzer Upload Windows ASan': 'libfuzzer_windows_asan_release_bot_reclient',
       'Libfuzzer Upload iOS Catalyst Debug': 'ios_catalyst_debug_static_bot_compile_only_libfuzzer_asan_no_dsyms_no_remoting',
       'MSAN Release (chained origins)': 'msan_release_bot_reclient',
       'MSAN Release (no origins)': 'msan_no_origins_release_bot_reclient',
@@ -430,7 +430,7 @@
       'win-fieldtrial-rel': 'gpu_tests_release_bot_minimal_symbols_reclient',
       'win-pixel-builder-rel': 'release_bot_reclient',
       'win-upload-perfetto': 'release_bot_perfetto_zlib_reclient',
-      'win10-code-coverage': 'clang_code_coverage',
+      'win10-code-coverage': 'clang_code_coverage_reclient',
       'win32-archive-rel-goma-rbe-canary': 'release_bot_x86_minimal_symbols_enable_archive_compression',
       'win32-archive-rel-goma-rbe-latest': 'release_bot_x86_minimal_symbols_enable_archive_compression',
       'win32-arm64-rel': 'win32_arm64_release_bot_reclient',
@@ -2174,6 +2174,10 @@
       'use_clang_coverage', 'debug_static_bot', 'x64', 'ios', 'xctest', 'ios_disable_xcode_project_generation',
     ],
 
+    'clang_code_coverage_reclient': [
+      'release_bot_reclient', 'clang', 'use_clang_coverage', 'no_symbols',
+    ],
+
     'clang_tot_asan_lsan_static_release': [
       'clang_tot', 'asan', 'lsan', 'static', 'release',
     ],
@@ -2938,6 +2942,13 @@
       'libfuzzer', 'asan', 'release_bot', 'chrome_with_codecs', 'pdf_xfa', 'disable_nacl', 'minimal_symbols', 'mojo_fuzzer',
     ],
 
+    # Note that because of optimize_for_fuzzing, Windows cannot share a config
+    # with other libFuzzer builds. optimize_for_fuzzing is used by the other
+    # libFuzzer build configs but it does not work on Windows.
+    'libfuzzer_windows_asan_release_bot_reclient': [
+      'libfuzzer', 'asan', 'release_bot_reclient', 'chrome_with_codecs', 'pdf_xfa', 'disable_nacl', 'minimal_symbols', 'mojo_fuzzer',
+    ],
+
     'libfuzzer_windows_asan_release_trybot': [
       'libfuzzer', 'asan', 'release_trybot', 'chrome_with_codecs', 'pdf_xfa', 'disable_nacl', 'mojo_fuzzer', 'skip_generate_fuzzer_owners', 'no_symbols',
     ],
diff --git a/tools/mb/mb_config_expectations/chromium.fuzz.json b/tools/mb/mb_config_expectations/chromium.fuzz.json
index 2446ab12..ac3ba14a 100644
--- a/tools/mb/mb_config_expectations/chromium.fuzz.json
+++ b/tools/mb/mb_config_expectations/chromium.fuzz.json
@@ -357,8 +357,9 @@
       "pdf_enable_xfa": true,
       "proprietary_codecs": true,
       "symbol_level": 1,
-      "use_goma": true,
-      "use_libfuzzer": true
+      "use_libfuzzer": true,
+      "use_rbe": true,
+      "use_remoteexec": true
     }
   },
   "Libfuzzer Upload iOS Catalyst Debug": {
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json
index cdffc7e..3f28e21 100644
--- a/tools/mb/mb_config_expectations/chromium.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -1381,7 +1381,8 @@
       "is_debug": false,
       "symbol_level": 0,
       "use_clang_coverage": true,
-      "use_goma": true
+      "use_rbe": true,
+      "use_remoteexec": true
     }
   },
   "win32-archive-rel-goma-rbe-canary": {
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml
index e0812a45..a2d1d89 100644
--- a/tools/metrics/histograms/metadata/ash/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -3244,6 +3244,17 @@
   </summary>
 </histogram>
 
+<histogram name="Ash.Projector.PendingScreencastChangeInterval" units="ms"
+    expires_after="2023-04-15">
+  <owner>xiqiruan@chromium.org</owner>
+  <owner>cros-projector@google.com</owner>
+  <summary>
+    Tracks the interval between UI updates during screencast uploading. Recorded
+    at each pending screencast's UI change except for the first one of current
+    uploading phase.
+  </summary>
+</histogram>
+
 <histogram name="Ash.Projector.Toolbar.{TabletOrClamshell}"
     enum="ProjectorToolbar" expires_after="2022-12-01">
   <owner>tobyhuang@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/memory/histograms.xml b/tools/metrics/histograms/metadata/memory/histograms.xml
index 926a62d..0b4375ae 100644
--- a/tools/metrics/histograms/metadata/memory/histograms.xml
+++ b/tools/metrics/histograms/metadata/memory/histograms.xml
@@ -2554,6 +2554,19 @@
   </summary>
 </histogram>
 
+<histogram name="Memory.RenderProcessHost.Count.SandboxedIframeOverhead"
+    units="processes" expires_after="2023-05-09">
+  <owner>wjmaclean@chromium.org</owner>
+  <owner>alexmos@chromium.org</owner>
+  <owner>creis@chromium.org</owner>
+  <summary>
+    The number of renderer processes that represent sandboxed iframes, computed
+    by counting the number of RenderProcessHosts allocated to them. This will be
+    zero when SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled() is
+    false. Recorded once per UMA ping.
+  </summary>
+</histogram>
+
 <histogram name="Memory.RenderProcessHost.Percent.OriginAgentClusterOverhead"
     units="%" expires_after="2022-09-28">
   <owner>wjmaclean@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml
index dae0cf1..7451044 100644
--- a/tools/metrics/histograms/metadata/password/histograms.xml
+++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -1848,6 +1848,19 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.MigratedSettingsUPMAndroid"
+    enum="BooleanEnabled" expires_after="M106">
+  <owner>ioanap@chromium.org</owner>
+  <owner>kazinova@google.com</owner>
+  <summary>
+    Records true when a settings migration occurs as part of the UPM transition.
+    It is recorded when the settings service (profile-scoped) is instantiated in
+    a Chrome client with UPM enabled if a migration hasn't already occured. Note
+    that if UPM is disabled, the next time it is enabled a new migration will
+    happen and be recorded.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.ModalLoadingDialog.{IntentType}.Outcome"
     enum="PasswordManager.LoadingDialogOutcome" expires_after="M106">
   <owner>maxan@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/search/histograms.xml b/tools/metrics/histograms/metadata/search/histograms.xml
index 99f86e32..004d038d 100644
--- a/tools/metrics/histograms/metadata/search/histograms.xml
+++ b/tools/metrics/histograms/metadata/search/histograms.xml
@@ -891,7 +891,10 @@
 </histogram>
 
 <histogram name="Search.ContextualSearchScreenTopSuppressed"
-    enum="ContextualSearchTapSuppression" expires_after="M72">
+    enum="ContextualSearchTapSuppression" expires_after="M103">
+  <obsolete>
+    Removed as of 05/2022
+  </obsolete>
   <owner>donnd@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -955,7 +958,10 @@
 </histogram>
 
 <histogram name="Search.ContextualSearchTapDurationNotSeen" units="ms"
-    expires_after="M72">
+    expires_after="M103">
+  <obsolete>
+    Removed as of 05/2022
+  </obsolete>
   <owner>donnd@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -966,7 +972,10 @@
 </histogram>
 
 <histogram name="Search.ContextualSearchTapDurationSeen" units="ms"
-    expires_after="M72">
+    expires_after="M103">
+  <obsolete>
+    Removed as of 05/2022
+  </obsolete>
   <owner>donnd@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -989,7 +998,10 @@
 </histogram>
 
 <histogram name="Search.ContextualSearchTapLongDurationSeen"
-    enum="ContextualSearchResultsSeen" expires_after="M72">
+    enum="ContextualSearchResultsSeen" expires_after="M103">
+  <obsolete>
+    Removed as of 05/2022
+  </obsolete>
   <owner>donnd@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -999,7 +1011,10 @@
 </histogram>
 
 <histogram name="Search.ContextualSearchTapShortDurationSeen"
-    enum="ContextualSearchResultsSeen" expires_after="M72">
+    enum="ContextualSearchResultsSeen" expires_after="M103">
+  <obsolete>
+    Removed as of 05/2022
+  </obsolete>
   <owner>donnd@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -1051,7 +1066,10 @@
 </histogram>
 
 <histogram name="Search.ContextualSearchTopLocationNotSeen" units="dps"
-    expires_after="M72">
+    expires_after="M103">
+  <obsolete>
+    Removed as of 05/2022
+  </obsolete>
   <owner>donnd@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -1061,7 +1079,10 @@
 </histogram>
 
 <histogram name="Search.ContextualSearchTopLocationSeen" units="dps"
-    expires_after="M72">
+    expires_after="M103">
+  <obsolete>
+    Removed as of 05/2022
+  </obsolete>
   <owner>donnd@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/security/histograms.xml b/tools/metrics/histograms/metadata/security/histograms.xml
index f7a6fab..5b5023c 100644
--- a/tools/metrics/histograms/metadata/security/histograms.xml
+++ b/tools/metrics/histograms/metadata/security/histograms.xml
@@ -720,6 +720,53 @@
   </summary>
 </histogram>
 
+<histogram name="SiteIsolation.IsolatableSandboxedIframes" units="processes"
+    expires_after="2023-05-09">
+  <owner>wjmaclean@chromium.org</owner>
+  <owner>alexmos@chromium.org</owner>
+  <owner>creis@chromium.org</owner>
+  <summary>
+    The number of sandboxed iframes that (i) are same-site (and therefore not
+    already process-isolated) and (ii) eligible to be process isolated if
+    SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled() is true. A
+    sandboxed iframe is eligible for process-isolation so long as it doesn't
+    have `allow-same-origin` among its sandbox permissions, and it isn't an
+    about:blank url. This metric measures the upper bound on the process
+    overhead of isolating sandboxed iframes, namely the case where every
+    sandboxed iframe is placed in its own process. Note that the computation of
+    this metric is independent of the current process model. Recorded once per
+    UMA ping.
+  </summary>
+</histogram>
+
+<histogram name="SiteIsolation.IsolatableSandboxedIframes.UniqueOrigins"
+    units="processes" expires_after="2023-05-09">
+  <owner>wjmaclean@chromium.org</owner>
+  <owner>alexmos@chromium.org</owner>
+  <owner>creis@chromium.org</owner>
+  <summary>
+    The number of unique origins among the sandboxed iframes reported in
+    SiteIsolation.IsolatableSandboxedIframes. Used to estimate the potential
+    process overhead if a per-origin process model is used for isolating the
+    sandboxed iframes instead of the (current) per-site process model. Note that
+    the computation of this metric is independent of the current process model.
+    Recorded once per UMA ping.
+  </summary>
+</histogram>
+
+<histogram name="SiteIsolation.IsolatableSandboxedIframes.UniqueSites"
+    units="processes" expires_after="2023-05-09">
+  <owner>wjmaclean@chromium.org</owner>
+  <owner>alexmos@chromium.org</owner>
+  <owner>creis@chromium.org</owner>
+  <summary>
+    The number of unique sites among the sandboxed iframes reported in
+    SiteIsolation.IsolatableSandboxedIframes. Note that the computation of this
+    metric is independent of the current process model. Recorded once per UMA
+    ping.
+  </summary>
+</histogram>
+
 <histogram name="SiteIsolation.IsPasswordFormSubmittedInDedicatedProcess"
     enum="SiteIsolationIsDedicatedProcess" expires_after="2022-08-07">
   <owner>alexmos@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/stability/histograms.xml b/tools/metrics/histograms/metadata/stability/histograms.xml
index 90600923..c5ace32 100644
--- a/tools/metrics/histograms/metadata/stability/histograms.xml
+++ b/tools/metrics/histograms/metadata/stability/histograms.xml
@@ -354,7 +354,7 @@
 </histogram>
 
 <histogram name="Stability.IOS.Crashpad.Initialized" enum="BooleanSuccess"
-    expires_after="2022-06-15">
+    expires_after="2023-05-03">
   <owner>justincohen@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 1d4c132a..06f34427 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -13,16 +13,16 @@
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "mac": {
-            "hash": "7d24e1bbb6c3e957962f3341559c4e7a825225e1",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/fbdedcfb33db2b18f8679550a31e2a062f466dab/trace_processor_shell"
+            "hash": "4cefd62893a9c1f47a57c4b0f4f3e1a16024f931",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/c69474dfc2a2002dd20ca6a62d65bb33757371f8/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "e1ad4861384b06d911a65f035317914b8cc975c6",
             "full_remote_path": "perfetto-luci-artifacts/v25.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "c0bff359879951f085fa474c3748f76fd29e9255",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/0d5910799e4742b15383c203b3c9a0583c9f1f88/trace_processor_shell"
+            "hash": "9d3f67f2c963b514c56233a2b64ffab2c99e640f",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/478630351306440b9bfb971ee7914704fecacd75/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/accessibility/ax_event_generator.h b/ui/accessibility/ax_event_generator.h
index dc81e0c..3f3f0a45 100644
--- a/ui/accessibility/ax_event_generator.h
+++ b/ui/accessibility/ax_event_generator.h
@@ -160,9 +160,14 @@
     const EventParams& event_params;
   };
 
-  class AX_EXPORT Iterator
-      : public std::iterator<std::input_iterator_tag, TargetedEvent> {
+  class AX_EXPORT Iterator {
    public:
+    using iterator_category = std::input_iterator_tag;
+    using value_type = TargetedEvent;
+    using difference_type = std::ptrdiff_t;
+    using pointer = TargetedEvent*;
+    using reference = TargetedEvent&;
+
     Iterator(
         std::map<AXNodeID, std::set<EventParams>>::const_iterator
             map_start_iter,
diff --git a/ui/base/models/dialog_model.cc b/ui/base/models/dialog_model.cc
index 27dafc256..30b1acd5 100644
--- a/ui/base/models/dialog_model.cc
+++ b/ui/base/models/dialog_model.cc
@@ -3,9 +3,11 @@
 // found in the LICENSE file.
 
 #include "ui/base/models/dialog_model.h"
+#include <memory>
 
 #include "base/callback_helpers.h"
 #include "base/ranges/algorithm.h"
+#include "ui/base/models/dialog_model_field.h"
 
 namespace ui {
 
@@ -102,6 +104,10 @@
       GetPassKey(), this, std::move(label), std::move(combobox_model), params));
 }
 
+void DialogModel::AddSeparator() {
+  AddField(std::make_unique<DialogModelSeparator>(GetPassKey(), this));
+}
+
 void DialogModel::AddTextfield(std::u16string label,
                                std::u16string text,
                                const DialogModelTextfield::Params& params) {
diff --git a/ui/base/models/dialog_model.h b/ui/base/models/dialog_model.h
index 64cbbc59..3dca06b 100644
--- a/ui/base/models/dialog_model.h
+++ b/ui/base/models/dialog_model.h
@@ -220,6 +220,12 @@
       return *this;
     }
 
+    // Adds a separator. See DialogModel::AddSeparator().
+    Builder& AddSeparator() {
+      model_->AddSeparator();
+      return *this;
+    }
+
     // Adds a textfield. See DialogModel::AddTextfield().
     Builder& AddTextfield(std::u16string label,
                           std::u16string text,
@@ -272,6 +278,9 @@
                    const DialogModelCombobox::Params& params =
                        DialogModelCombobox::Params());
 
+  // Adds a separator at the end of the dialog model.
+  void AddSeparator();
+
   // Adds a labeled textfield (label: [text]) at the end of the dialog model.
   void AddTextfield(std::u16string label,
                     std::u16string text,
diff --git a/ui/base/models/dialog_model_field.cc b/ui/base/models/dialog_model_field.cc
index 774cfef..3193573 100644
--- a/ui/base/models/dialog_model_field.cc
+++ b/ui/base/models/dialog_model_field.cc
@@ -166,12 +166,7 @@
 DialogModelBodyText::DialogModelBodyText(base::PassKey<DialogModel> pass_key,
                                          DialogModel* model,
                                          const DialogModelLabel& label)
-    : DialogModelField(pass_key,
-                       model,
-                       kBodyText,
-                       -1,
-                       base::flat_set<Accelerator>()),
-      label_(label) {}
+    : DialogModelField(pass_key, model, kBodyText, -1, {}), label_(label) {}
 
 DialogModelBodyText::~DialogModelBodyText() = default;
 
@@ -181,11 +176,7 @@
     int unique_id,
     const DialogModelLabel& label,
     const DialogModelCheckbox::Params& params)
-    : DialogModelField(pass_key,
-                       model,
-                       kCheckbox,
-                       unique_id,
-                       base::flat_set<Accelerator>()),
+    : DialogModelField(pass_key, model, kCheckbox, unique_id, {}),
       label_(label),
       is_checked_(params.is_checked_) {}
 
@@ -247,6 +238,12 @@
     callback_.Run();
 }
 
+DialogModelSeparator::DialogModelSeparator(base::PassKey<DialogModel> pass_key,
+                                           DialogModel* model)
+    : DialogModelField(pass_key, model, kSeparator, -1, {}) {}
+
+DialogModelSeparator::~DialogModelSeparator() = default;
+
 DialogModelTextfield::Params::Params() = default;
 DialogModelTextfield::Params::~Params() = default;
 
@@ -292,11 +289,7 @@
     DialogModel* model,
     int unique_id,
     std::unique_ptr<DialogModelCustomField::Factory> factory)
-    : DialogModelField(pass_key,
-                       model,
-                       kCustom,
-                       unique_id,
-                       base::flat_set<Accelerator>()),
+    : DialogModelField(pass_key, model, kCustom, unique_id, {}),
       factory_(std::move(factory)) {}
 
 DialogModelCustomField::~DialogModelCustomField() = default;
diff --git a/ui/base/models/dialog_model_field.h b/ui/base/models/dialog_model_field.h
index 9ddc657a..e17aa3e 100644
--- a/ui/base/models/dialog_model_field.h
+++ b/ui/base/models/dialog_model_field.h
@@ -107,7 +107,15 @@
 // stays in sync with the visible dialog (through DialogModelHosts).
 class COMPONENT_EXPORT(UI_BASE) DialogModelField {
  public:
-  enum Type { kButton, kBodyText, kCheckbox, kCombobox, kTextfield, kCustom };
+  enum Type {
+    kButton,
+    kBodyText,
+    kCheckbox,
+    kCombobox,
+    kCustom,
+    kSeparator,
+    kTextfield
+  };
 
   DialogModelField(const DialogModelField&) = delete;
   DialogModelField& operator=(const DialogModelField&) = delete;
@@ -343,6 +351,17 @@
   base::RepeatingClosure callback_;
 };
 
+// Field class representing a separator.
+class COMPONENT_EXPORT(UI_BASE) DialogModelSeparator : public DialogModelField {
+ public:
+  // Note that this is constructed through a DialogModel which adds it to model
+  // fields.
+  DialogModelSeparator(base::PassKey<DialogModel> pass_key, DialogModel* model);
+  DialogModelSeparator(const DialogModelSeparator&) = delete;
+  DialogModelSeparator& operator=(const DialogModelSeparator&) = delete;
+  ~DialogModelSeparator() override;
+};
+
 // Field class representing a textfield and corresponding label to describe the
 // textfield:
 //
@@ -422,8 +441,8 @@
       DialogModel* model,
       int unique_id,
       std::unique_ptr<DialogModelCustomField::Factory> factory);
-  DialogModelCustomField(const DialogModelTextfield&) = delete;
-  DialogModelCustomField& operator=(const DialogModelTextfield&) = delete;
+  DialogModelCustomField(const DialogModelCustomField&) = delete;
+  DialogModelCustomField& operator=(const DialogModelCustomField&) = delete;
   ~DialogModelCustomField() override;
 
   // Methods with base::PassKey<DialogModelHost> are only intended to be called
diff --git a/ui/events/ozone/evdev/event_device_info.cc b/ui/events/ozone/evdev/event_device_info.cc
index 93dc643..da6dbc4 100644
--- a/ui/events/ozone/evdev/event_device_info.cc
+++ b/ui/events/ozone/evdev/event_device_info.cc
@@ -8,6 +8,7 @@
 
 #include <cstring>
 
+#include "base/containers/fixed_flat_set.h"
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
@@ -33,11 +34,20 @@
 // unusual.
 const size_t kMaximumDeviceNameLength = 256;
 
-constexpr struct {
+struct DeviceId {
   uint16_t vendor;
   uint16_t product_id;
-} kKeyboardBlocklist[] = {
+  constexpr bool operator<(const DeviceId& other) const {
+    return vendor == other.vendor ? product_id < other.product_id
+                                  : vendor < other.vendor;
+  }
+};
+
+constexpr auto kKeyboardBlocklist = base::MakeFixedFlatSet<DeviceId>({
+    {0x0111, 0x1830},  // SteelSeries Rival 3 Wireless (Bluetooth)
     {0x0111, 0x183a},  // SteelSeries Aerox 3 Wireless (Bluetooth)
+    {0x0111, 0x1854},  // SteelSeries Aerox 5 Wireless (Bluetooth)
+    {0x0111, 0x185a},  // SteelSeries Aerox 9 Wireless (Bluetooth)
     {0x03f0, 0xa407},  // HP X4000 Wireless Mouse
     {0x045e, 0x0745},  // Microsoft Wireless Mobile Mouse 6000
     {0x045e, 0x0821},  // Microsoft Surface Precision Mouse
@@ -71,23 +81,162 @@
     {0x046d, 0xc093},  // Logitech M500s
     {0x046d, 0xc534},  // Logitech M170
     {0x046d, 0xc53e},  // Logitech Spotlight Presentation Remote (USB dongle)
+    {0x04b4, 0x121f},  // SteelSeries Ikari
     {0x056e, 0x0134},  // Elecom Enelo IR LED Mouse 350
     {0x056e, 0x0141},  // Elecom EPRIM Blue LED 5 button mouse 228
     {0x056e, 0x0159},  // Elecom Blue LED Mouse 203
-    {0x05e0, 0x1200},  // Zebra LS2208 barcode scanner
+    {0x05e0, 0x1200},  // Symbol Technologies / Zebra LS2208 barcode scanner
     {0x0951, 0x1727},  // HyperX Pulsefire Haste Gaming Mouse
     {0x0c45, 0x7403},  // RDing FootSwitch1F1
-    {0x1038, 0x1369},  // SteelSeries Sensei RAW Frost Blue
-    {0x1038, 0x1824},  // SteelSeries Rival 3 Wired
-    {0x1038, 0x1830},  // SteelSeries Rival 3 Wireless (USB dongle)
+    {0x1038, 0x0470},  // SteelSeries Reaper Edge
+    {0x1038, 0x0471},  // SteelSeries Rival Rescuer
+    {0x1038, 0x0472},  // SteelSeries Rival 150 net café
+    {0x1038, 0x0473},  // SteelSeries Sensei SP
+    {0x1038, 0x0475},  // SteelSeries Rival 160 retail
+    {0x1038, 0x0777},  // SteelSeries MO3
+    {0x1038, 0x1300},  // SteelSeries Kinzu
+    {0x1038, 0x1310},  // SteelSeries MO4
+    {0x1038, 0x1311},  // SteelSeries MO4v2
+    {0x1038, 0x1320},  // SteelSeries MO3v2
+    {0x1038, 0x1330},  // SteelSeries MO5
+    {0x1038, 0x1332},  // SteelSeries MO5 (Dongle)
+    {0x1038, 0x1356},  // SteelSeries Sensei Dark EDG
+    {0x1038, 0x1358},  // SteelSeries Sensei Dark Snake
+    {0x1038, 0x135a},  // SteelSeries Sensei Dell Alienware
+    {0x1038, 0x1360},  // SteelSeries Xai
+    {0x1038, 0x1361},  // SteelSeries Sensei
+    {0x1038, 0x1362},  // SteelSeries Sensei Raw Diablo III Mouse
+    {0x1038, 0x1364},  // SteelSeries Kana
+    {0x1038, 0x1366},  // SteelSeries Kinzu 2
+    {0x1038, 0x1369},  // SteelSeries Sensei Raw
+    {0x1038, 0x136b},  // SteelSeries MLG Sensei
+    {0x1038, 0x136d},  // SteelSeries Sensei Raw: GW2
+    {0x1038, 0x136f},  // SteelSeries Sensei Raw: CoD
+    {0x1038, 0x1370},  // SteelSeries Sensei Master
+    {0x1038, 0x1372},  // SteelSeries Sensei Master (Hub Controller)
+    {0x1038, 0x1373},  // SteelSeries Sensei Master (Flash Drive Controller)
+    {0x1038, 0x1374},  // SteelSeries Kana: CS:GO
+    {0x1038, 0x1376},  // SteelSeries Kana: DOTA
+    {0x1038, 0x1378},  // SteelSeries Kinzu v2.1
+    {0x1038, 0x137a},  // SteelSeries Kana Pro
+    {0x1038, 0x137c},  // SteelSeries Wireless Sensei
+    {0x1038, 0x137e},  // SteelSeries Wireless Sensei (Charge Stand)
+    {0x1038, 0x1380},  // SteelSeries World of Tank mouse
+    {0x1038, 0x1382},  // SteelSeries Sims Mouse
+    {0x1038, 0x1384},  // SteelSeries Rival
+    {0x1038, 0x1386},  // SteelSeries SIMS 4 mouse
+    {0x1038, 0x1388},  // SteelSeries Kinzu v3 Mouse
+    {0x1038, 0x1390},  // SteelSeries Sensei Raw Heroes of the Storm Mouse
+    {0x1038, 0x1392},  // SteelSeries Rival DOTA 2
+    {0x1038, 0x1394},  // SteelSeries Rival 300 CS:GO Fade Edition
+    {0x1038, 0x1396},  // SteelSeries Rival 300 Gaming Mouse
+    {0x1038, 0x1700},  // SteelSeries Rival 700
+    {0x1038, 0x1701},  // SteelSeries Rival 700 (Basic)
+    {0x1038, 0x1702},  // SteelSeries Rival 100 Gaming Mouse (ELM4 - A)
+    {0x1038, 0x1704},  // SteelSeries Rival 95 PC BANG
+    {0x1038, 0x1705},  // SteelSeries Rival 100 For Alienware
+    {0x1038, 0x1706},  // SteelSeries Rival 95
+    {0x1038, 0x1707},  // SteelSeries Rival 95 MSI edition
+    {0x1038, 0x1708},  // SteelSeries Rival 100 Gaming Mouse (PC Bang)
+    {0x1038, 0x1709},  // SteelSeries Rival 50 MSI edition
+    {0x1038, 0x170a},  // SteelSeries Rival 100 Dell China
+    {0x1038, 0x170b},  // SteelSeries Rival 100 DOTA 2 Mouse
+    {0x1038, 0x170c},  // SteelSeries Rival 100 DOTA 2 Mouse (Lenovo)
+    {0x1038, 0x170d},  // SteelSeries Rival 100 World of Tanks Mouse
+    {0x1038, 0x170e},  // SteelSeries Rival 500 (MBM)
+    {0x1038, 0x170f},  // SteelSeries Rival 500 (Basic)
+    {0x1038, 0x1710},  // SteelSeries Rival 300 Gaming Mouse
+    {0x1038, 0x1712},  // SteelSeries Rival 300 Fallout 4 Gaming Mouse
+    {0x1038, 0x1714},  // SteelSeries Rival 300 Predator Gaming Mouse
+    {0x1038, 0x1716},  // SteelSeries Rival 300 CS:GO Fade Edition
+    {0x1038, 0x1718},  // SteelSeries Rival 300 HP Omen
+    {0x1038, 0x171a},  // SteelSeries Rival 300 CS:GO Hyperbeast Edition
+    {0x1038, 0x171c},  // SteelSeries Rival 300 Evil Geniuses Edition
+    {0x1038, 0x171e},  // SteelSeries Rival 310 CSGO Howl
+    {0x1038, 0x171f},  // SteelSeries Rival 310 CSGO Howl (Basic)
+    {0x1038, 0x1720},  // SteelSeries Rival 310
+    {0x1038, 0x1721},  // SteelSeries Rival 310 (Basic)
+    {0x1038, 0x1722},  // SteelSeries Sensei 310
+    {0x1038, 0x1723},  // SteelSeries Sensei 310  (Basic)
+    {0x1038, 0x1724},  // SteelSeries Rival 600
+    {0x1038, 0x1725},  // SteelSeries Rival 600 (Basic)
+    {0x1038, 0x1726},  // SteelSeries Rival 650 Wireless
+    {0x1038, 0x1727},  // SteelSeries Rival 650 Wireless (Basic)
+    {0x1038, 0x1729},  // SteelSeries Rival 110 Gaming Mouse
+    {0x1038, 0x172b},  // SteelSeries Rival 650 Wireless (Wired)
+    {0x1038, 0x172c},  // SteelSeries Rival 650 Wireless (Basic for wired)
+    {0x1038, 0x172d},  // SteelSeries Rival 110 (Dell)
+    {0x1038, 0x172e},  // SteelSeries Rival 600 Dota 2
+    {0x1038, 0x172f},  // SteelSeries Rival 600 Dota 2 (Basic)
+    {0x1038, 0x1730},  // SteelSeries Rival 710
+    {0x1038, 0x1731},  // SteelSeries Rival 710 (Basic)
+    {0x1038, 0x1736},  // SteelSeries Rival 310 PUBG Edition
+    {0x1038, 0x1737},  // SteelSeries Rival 310 PUBG Edition (Basic)
+    {0x1038, 0x1800},  // SteelSeries Sensei Raw Optical
+    {0x1038, 0x1801},  // SteelSeries Sensei Raw Optical (Basic)
+    {0x1038, 0x1802},  // SteelSeries Sensei Raw Optical RGB
+    {0x1038, 0x1803},  // SteelSeries Sensei Raw Optical RGB (Basic)
+    {0x1038, 0x1810},  // SteelSeries Rival 300S
+    {0x1038, 0x1812},  // SteelSeries Rival 300S Dell Silver
+    {0x1038, 0x1814},  // SteelSeries Rival 105 (Kana v3) Gaming Mouse
+    {0x1038, 0x1816},  // SteelSeries Rival 106 Gaming Mouse
+    {0x1038, 0x1818},  // SteelSeries Rival 610 Wireless
+    {0x1038, 0x1819},  // SteelSeries Rival 610 Wireless (Basic)
+    {0x1038, 0x181a},  // SteelSeries Rival 610 Wireless (Wired)
+    {0x1038, 0x181b},  // SteelSeries Rival 610 Wireless (Basic for wired)
+    {0x1038, 0x181c},  // SteelSeries Rival 310 Wireless
+    {0x1038, 0x181d},  // SteelSeries Rival 310 Wireless (Basic)
+    {0x1038, 0x181e},  // SteelSeries Rival 310 Wireless (Wired)
+    {0x1038, 0x181f},  // SteelSeries Rival 310 Wireless (Basic for wired)
+    {0x1038, 0x1820},  // SteelSeries Rival 610
+    {0x1038, 0x1821},  // SteelSeries Rival 610 (Basic)
+    {0x1038, 0x1822},  // SteelSeries Sensei 610
+    {0x1038, 0x1823},  // SteelSeries Sensei 610 (Basic)
+    {0x1038, 0x1824},  // SteelSeries Rival 3
+    {0x1038, 0x1826},  // SteelSeries Sensei Raw Optical RGB v2
+    {0x1038, 0x1827},  // SteelSeries Sensei Raw Optical RGB v2 (Basic)
+    {0x1038, 0x1828},  // SteelSeries Radical Wireless
+    {0x1038, 0x1829},  // SteelSeries Radical Wireless (Basic)
+    {0x1038, 0x182a},  // SteelSeries Prime Rainbow Six Edition
+    {0x1038, 0x182b},  // SteelSeries Prime Rainbow Six Edition (Basic)
+    {0x1038, 0x182c},  // SteelSeries Prime+
+    {0x1038, 0x182d},  // SteelSeries Prime+ (Basic)
+    {0x1038, 0x182e},  // SteelSeries Prime
+    {0x1038, 0x182f},  // SteelSeries Prime (Basic)
+    {0x1038, 0x1830},  // SteelSeries Rival 3 Wireless
+    {0x1038, 0x1831},  // SteelSeries Rival 3 Wireless (Basic)
+    {0x1038, 0x1832},  // SteelSeries Sensei Ten
+    {0x1038, 0x1833},  // SteelSeries Sensei Ten (Basic)
+    {0x1038, 0x1834},  // SteelSeries Sensei Ten Neon Rider Edition
+    {0x1038, 0x1835},  // SteelSeries Sensei Ten Neon Rider Edition (Basic)
     {0x1038, 0x1836},  // SteelSeries Aerox 3
-    {0x1038, 0x183a},  // SteelSeries Aerox 3 Wireless (USB dongle)
+    {0x1038, 0x1838},  // SteelSeries Aerox 3 Wireless (Dongle)
+    {0x1038, 0x1839},  // SteelSeries Aerox 3 Wireless (Basic for dongle)
+    {0x1038, 0x183a},  // SteelSeries Aerox 3 Wireless (Wired)
+    {0x1038, 0x183b},  // SteelSeries Aerox 3 Wireless (Basic for wired)
+    {0x1038, 0x183c},  // SteelSeries Rival 5
+    {0x1038, 0x183d},  // SteelSeries Rival 5 (Basic)
+    {0x1038, 0x183e},  // SteelSeries Rival 5 Destiny 2
+    {0x1038, 0x183f},  // SteelSeries Rival 5 Destiny 2 (Basic)
+    {0x1038, 0x1840},  // SteelSeries Prime Wireless (Dongle)
+    {0x1038, 0x1841},  // SteelSeries Prime Wireless (Basic for dongle)
+    {0x1038, 0x1842},  // SteelSeries Prime Wireless (Wired)
+    {0x1038, 0x1843},  // SteelSeries Prime Wireless (Basic for wired)
+    {0x1038, 0x1848},  // SteelSeries Prime Mini Wireless (Dongle)
+    {0x1038, 0x184a},  // SteelSeries Prime Mini Wireless (Wired)
+    {0x1038, 0x184c},  // SteelSeries Rival 3 (NVIDIA Support - Standard)
+    {0x1038, 0x184d},  // SteelSeries Prime Mini
+    {0x1038, 0x1850},  // SteelSeries Aerox 5
+    {0x1038, 0x1852},  // SteelSeries Aerox 5 Wireless (Dongle)
+    {0x1038, 0x1854},  // SteelSeries Aerox 5 Wireless (Wired)
+    {0x1038, 0x1856},  // SteelSeries Prime CS:GO Neo Noir
+    {0x1038, 0x1858},  // SteelSeries Aerox 9 WL (Dongle)
+    {0x1038, 0x185a},  // SteelSeries Aerox 9 WL (Wired)
     {0x1050, 0x0010},  // Yubico.com Yubikey
     {0x1050, 0x0407},  // Yubico.com Yubikey 4 OTP+U2F+CCID
     {0x1532, 0x007a},  // Razer Viper Ultimate (Wired)
     {0x1532, 0x007b},  // Razer Viper Ultimate (Wireless)
     {0x17ef, 0x60e4},  // Lenovo Legion M300 RGB Gaming Mouse
-                       // (which can send keystrokes as part of macros.)
     {0x17ef, 0x6123},  // Lenovo USB-C Wired Compact Mouse
     {0x1b1c, 0x1b7a},  // Corsair Sabre Pro Champion Gaming Mouse
     {0x1b1c, 0x1b94},  // Corsair Katar Pro Wireless (USB dongle)
@@ -100,21 +249,15 @@
     {0x28bd, 0x0914},  // XP-Pen Star G640
     {0x28bd, 0x091f},  // XP-Pen Artist 12 Pro
     {0x28bd, 0x0928},  // XP-Pen Deco mini7W
-};
+});
 
-constexpr struct {
-  uint16_t vendor;
-  uint16_t product_id;
-} kStylusButtonDevices[] = {
+constexpr DeviceId kStylusButtonDevices[] = {
     {0x413c, 0x81d5},  // Dell Active Pen PN579X
 };
 
 // Certain devices need to be forced to use libinput in place of
 // evdev/libgestures
-constexpr struct {
-  uint16_t vendor;
-  uint16_t product_id;
-} kForceLibinputlist[] = {
+constexpr DeviceId kForceLibinputlist[] = {
     {0x0002, 0x000e},  // HP Stream 14 touchpad
     {0x044e, 0x120a},  // Dell Latitude 3480 touchpad
 };
@@ -594,13 +737,8 @@
 }
 
 bool IsInKeyboardBlockList(input_id input_id_) {
-  for (const auto& blocklist_id : kKeyboardBlocklist) {
-    if (input_id_.vendor == blocklist_id.vendor &&
-        input_id_.product == blocklist_id.product_id)
-      return true;
-  }
-
-  return false;
+  DeviceId id = {input_id_.vendor, input_id_.product};
+  return kKeyboardBlocklist.contains(id);
 }
 
 bool EventDeviceInfo::HasKeyboard() const {
diff --git a/ui/events/ozone/evdev/event_device_info_unittest.cc b/ui/events/ozone/evdev/event_device_info_unittest.cc
index 41b2e7a..d10eaa0 100644
--- a/ui/events/ozone/evdev/event_device_info_unittest.cc
+++ b/ui/events/ozone/evdev/event_device_info_unittest.cc
@@ -500,4 +500,22 @@
   EXPECT_EQ(ui::InputDeviceType::INPUT_DEVICE_INTERNAL, devinfo.device_type());
 }
 
+TEST(EventDeviceInfoTest, DeviceOnKeyboardBlocklist) {
+  EventDeviceInfo devinfo;
+  EXPECT_TRUE(CapabilitiesToDeviceInfo(kSymbolTechBarcodeScanner, &devinfo));
+
+  EXPECT_FALSE(devinfo.HasKeyboard());
+  EXPECT_FALSE(devinfo.HasMouse());
+  EXPECT_FALSE(devinfo.HasPointingStick());
+  EXPECT_FALSE(devinfo.HasTouchpad());
+  EXPECT_FALSE(devinfo.HasHapticTouchpad());
+  EXPECT_FALSE(devinfo.HasTouchscreen());
+  EXPECT_FALSE(devinfo.HasTablet());
+  EXPECT_FALSE(devinfo.HasGamepad());
+  EXPECT_FALSE(devinfo.IsStylusButtonDevice());
+  EXPECT_FALSE(devinfo.HasStylusSwitch());
+  EXPECT_FALSE(devinfo.HasValidMTAbsXY());
+  EXPECT_FALSE(devinfo.IsSemiMultitouch());
+}
+
 }  // namespace ui
diff --git a/ui/events/ozone/evdev/event_device_test_util.cc b/ui/events/ozone/evdev/event_device_test_util.cc
index e67b23c..e470b7e8 100644
--- a/ui/events/ozone/evdev/event_device_test_util.cc
+++ b/ui/events/ozone/evdev/event_device_test_util.cc
@@ -1465,6 +1465,33 @@
     std::size(kRedrixTouchpadAxes),
 };
 
+const DeviceCapabilities kSymbolTechBarcodeScanner = {
+    /* path */
+    "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-6/1-6:1.0/0003:05E0:1200.0009/"
+    "input/input27/event19",
+    /* name */ "Symbol Technologies, Inc, 2008 Symbol Bar Code Scanner",
+    /* phys */ "usb-0000:00:14.0-6/input0",
+    /* uniq */ "S/N:D698905D483448AD806AAC8CD63B8B4A Rev:PAACES00-002-R033",
+    /* bustype */ "0003",
+    /* vendor */ "05e0",
+    /* product */ "1200",
+    /* version */ "0110",
+    /* prop */ "0",
+    /* ev */ "120013",
+    /* key */
+    "1000000000007 ff9f207ac14057ff febeffdfffefffff fffffffffffffffe",
+    /* rel */ "0",
+    /* abs */ "0",
+    /* msc */ "10",
+    /* sw */ "0",
+    /* led */ "1f",
+    /* ff */ "0",
+    /* abs_axis */ nullptr,
+    /* abs_axis_count */ 0,
+    /* kbd_function_row_physmap */ "",
+    /* kbd_top_row_layout */ "",
+};
+
 // NB: Please use the capture_device_capabilities.py script to add more
 // test data here. This will help ensure the data matches what the kernel
 // reports for a real device and is entered correctly.
diff --git a/ui/events/ozone/evdev/event_device_test_util.h b/ui/events/ozone/evdev/event_device_test_util.h
index e22a8b27..2a99db9 100644
--- a/ui/events/ozone/evdev/event_device_test_util.h
+++ b/ui/events/ozone/evdev/event_device_test_util.h
@@ -115,6 +115,7 @@
 extern const DeviceCapabilities kDellLatitudeE6510Touchpad;
 extern const DeviceCapabilities kHPProBook6560bTouchpad;
 extern const DeviceCapabilities kJinlonKeyboard;
+extern const DeviceCapabilities kSymbolTechBarcodeScanner;
 }  // namespace ui
 
 #endif  // UI_EVENTS_OZONE_EVDEV_EVENT_DEVICE_TEST_UTIL_H_
diff --git a/ui/views/bubble/bubble_dialog_model_host.cc b/ui/views/bubble/bubble_dialog_model_host.cc
index e990f2d..1a124770 100644
--- a/ui/views/bubble/bubble_dialog_model_host.cc
+++ b/ui/views/bubble/bubble_dialog_model_host.cc
@@ -14,6 +14,7 @@
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/combobox_model.h"
 #include "ui/base/models/dialog_model.h"
+#include "ui/base/models/dialog_model_field.h"
 #include "ui/views/accessibility/accessibility_paint_checks.h"
 #include "ui/views/border.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
@@ -22,6 +23,7 @@
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/controls/separator.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/layout/box_layout.h"
@@ -48,6 +50,8 @@
       return BubbleDialogModelHost::FieldType::kControl;
     case ui::DialogModelField::kCombobox:
       return BubbleDialogModelHost::FieldType::kControl;
+    case ui::DialogModelField::kSeparator:
+      return BubbleDialogModelHost::FieldType::kMenuItem;
     case ui::DialogModelField::kCustom:
       return static_cast<BubbleDialogModelHost::CustomViewFactory*>(
                  field->AsCustomField(pass_key)->factory(pass_key))
@@ -407,6 +411,9 @@
     case ui::DialogModelField::kCombobox:
       AddOrUpdateCombobox(field->AsCombobox(GetPassKey()));
       break;
+    case ui::DialogModelField::kSeparator:
+      AddOrUpdateSeparator(field);
+      break;
     case ui::DialogModelField::kTextfield:
       AddOrUpdateTextfield(field->AsTextfield(GetPassKey()));
       break;
@@ -567,6 +574,17 @@
                           std::move(combobox), font_list);
 }
 
+void BubbleDialogModelHost::AddOrUpdateSeparator(
+    ui::DialogModelField* model_field) {
+  DCHECK_EQ(ui::DialogModelField::Type::kSeparator,
+            model_field->type(GetPassKey()));
+  // TODO(pbos): Support updates to the existing model.
+
+  auto separator = std::make_unique<Separator>();
+  DialogModelHostField info{model_field, separator.get(), nullptr};
+  AddDialogModelHostField(std::move(separator), info);
+}
+
 void BubbleDialogModelHost::AddOrUpdateTextfield(
     ui::DialogModelTextfield* model_field) {
   // TODO(pbos): Support updates to the existing model.
diff --git a/ui/views/bubble/bubble_dialog_model_host.h b/ui/views/bubble/bubble_dialog_model_host.h
index 5b6e2ef..cd303af 100644
--- a/ui/views/bubble/bubble_dialog_model_host.h
+++ b/ui/views/bubble/bubble_dialog_model_host.h
@@ -113,6 +113,7 @@
   void AddOrUpdateBodyText(ui::DialogModelBodyText* model_field);
   void AddOrUpdateCheckbox(ui::DialogModelCheckbox* model_field);
   void AddOrUpdateCombobox(ui::DialogModelCombobox* model_field);
+  void AddOrUpdateSeparator(ui::DialogModelField* model_field);
   void AddOrUpdateTextfield(ui::DialogModelTextfield* model_field);
 
   void UpdateSpacingAndMargins();
diff --git a/ui/views/highlight_border.cc b/ui/views/highlight_border.cc
index 94243c2..cd9845c 100644
--- a/ui/views/highlight_border.cc
+++ b/ui/views/highlight_border.cc
@@ -16,8 +16,6 @@
 
 namespace views {
 
-constexpr int kHighlightBorderThickness = 1;
-
 // static
 void HighlightBorder::PaintBorderToCanvas(
     gfx::Canvas* canvas,
@@ -26,34 +24,8 @@
     const gfx::RoundedCornersF& corner_radii,
     Type type,
     bool use_light_colors) {
-  ui::ColorId highlight_color_id;
-  ui::ColorId border_color_id;
-  if (use_light_colors) {
-    // TODO(crbug/1319917): These light color values are used here since we want
-    // to use light colors when dark/light mode feature is not enabled. This
-    // should be removed after dark light mode is launched.
-    DCHECK(!ash::features::IsDarkLightModeEnabled());
-    highlight_color_id = type == HighlightBorder::Type::kHighlightBorder1
-                             ? ui::kColorAshSystemUILightHighlightColor1
-                             : ui::kColorAshSystemUILightHighlightColor2;
-    border_color_id = type == HighlightBorder::Type::kHighlightBorder1
-                          ? ui::kColorAshSystemUILightBorderColor1
-                          : ui::kColorAshSystemUILightBorderColor2;
-  } else {
-    highlight_color_id = type == HighlightBorder::Type::kHighlightBorder1
-                             ? ui::kColorAshSystemUIHighlightColor1
-                             : ui::kColorAshSystemUIHighlightColor2;
-    border_color_id = type == HighlightBorder::Type::kHighlightBorder1
-                          ? ui::kColorAshSystemUIBorderColor1
-                          : ui::kColorAshSystemUIBorderColor2;
-  }
-
-  // `view` should be embedded in a Widget to use color provider.
-  DCHECK(view.GetWidget());
-  const SkColor inner_color =
-      view.GetColorProvider()->GetColor(highlight_color_id);
-  const SkColor outer_color =
-      view.GetColorProvider()->GetColor(border_color_id);
+  SkColor inner_color = GetHighlightColor(view, type, use_light_colors);
+  SkColor outer_color = GetBorderColor(view, type, use_light_colors);
 
   cc::PaintFlags flags;
   flags.setStrokeWidth(kHighlightBorderThickness);
@@ -90,6 +62,54 @@
   canvas->DrawPath(inner_path, flags);
 }
 
+// static
+SkColor HighlightBorder::GetHighlightColor(const views::View& view,
+                                           HighlightBorder::Type type,
+                                           bool use_light_colors) {
+  ui::ColorId highlight_color_id;
+  if (use_light_colors) {
+    // TODO(crbug/1319917): These light color values are used here since we want
+    // to use light colors when dark/light mode feature is not enabled. This
+    // should be removed after dark light mode is launched.
+    DCHECK(!ash::features::IsDarkLightModeEnabled());
+    highlight_color_id = type == HighlightBorder::Type::kHighlightBorder1
+                             ? ui::kColorAshSystemUILightHighlightColor1
+                             : ui::kColorAshSystemUILightHighlightColor2;
+  } else {
+    highlight_color_id = type == HighlightBorder::Type::kHighlightBorder1
+                             ? ui::kColorAshSystemUIHighlightColor1
+                             : ui::kColorAshSystemUIHighlightColor2;
+  }
+
+  // `view` should be embedded in a Widget to use color provider.
+  DCHECK(view.GetWidget());
+  return view.GetColorProvider()->GetColor(highlight_color_id);
+}
+
+// static
+SkColor HighlightBorder::GetBorderColor(const views::View& view,
+                                        HighlightBorder::Type type,
+                                        bool use_light_colors) {
+  ui::ColorId border_color_id;
+  if (use_light_colors) {
+    // TODO(crbug/1319917): These light color values are used here since we want
+    // to use light colors when dark/light mode feature is not enabled. This
+    // should be removed after dark light mode is launched.
+    DCHECK(!ash::features::IsDarkLightModeEnabled());
+    border_color_id = type == HighlightBorder::Type::kHighlightBorder1
+                          ? ui::kColorAshSystemUILightBorderColor1
+                          : ui::kColorAshSystemUILightBorderColor2;
+  } else {
+    border_color_id = type == HighlightBorder::Type::kHighlightBorder1
+                          ? ui::kColorAshSystemUIBorderColor1
+                          : ui::kColorAshSystemUIBorderColor2;
+  }
+
+  // `view` should be embedded in a Widget to use color provider.
+  DCHECK(view.GetWidget());
+  return view.GetColorProvider()->GetColor(border_color_id);
+}
+
 HighlightBorder::HighlightBorder(int corner_radius,
                                  Type type,
                                  bool use_light_colors,
diff --git a/ui/views/highlight_border.h b/ui/views/highlight_border.h
index 784e050..a8a2ff9c 100644
--- a/ui/views/highlight_border.h
+++ b/ui/views/highlight_border.h
@@ -15,6 +15,8 @@
 
 namespace views {
 
+constexpr int kHighlightBorderThickness = 1;
+
 // A rounded rectangle border that has inner (highlight) and outer color.
 // Useful when go/cros-launcher-spec mentions "BorderHighlight".
 class VIEWS_EXPORT HighlightBorder : public views::Border {
@@ -56,6 +58,16 @@
                                   Type type,
                                   bool use_light_colors);
 
+  // Returns the inner highlight color used to paint highlight border.
+  static SkColor GetHighlightColor(const views::View& view,
+                                   HighlightBorder::Type type,
+                                   bool use_light_colors);
+
+  // Returns the outer border color used to paint highlight border.
+  static SkColor GetBorderColor(const views::View& view,
+                                HighlightBorder::Type type,
+                                bool use_light_colors);
+
   HighlightBorder(int corner_radius,
                   Type type,
                   bool use_light_colors,
diff --git a/ui/webui/resources/css/BUILD.gn b/ui/webui/resources/css/BUILD.gn
index 41a44c5..5533d0c 100644
--- a/ui/webui/resources/css/BUILD.gn
+++ b/ui/webui/resources/css/BUILD.gn
@@ -25,7 +25,6 @@
   in_files = [
     "action_link.css",
     "apps/common.css",
-    "apps/topbutton_bar.css",
     "butter_bar.css",
     "chrome_shared.css",
     "dialogs.css",
diff --git a/ui/webui/resources/css/apps/topbutton_bar.css b/ui/webui/resources/css/apps/topbutton_bar.css
deleted file mode 100644
index 2979c0d..0000000
--- a/ui/webui/resources/css/apps/topbutton_bar.css
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright 2013 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-.topbutton-bar {
-  -webkit-box-align: center;
-  display: -webkit-box;
-}
-
-.topbutton-bar button {
-  -webkit-app-region: no-drag;
-  -webkit-box-shadow: none;
-  background-color: transparent;
-  background-image: none;
-  background-position: center;
-  background-repeat: no-repeat;
-  border: 0;
-  display: block;
-  height: 32px;
-  margin-inline-end: 10px;
-  min-width: 0;
-  outline: none;
-  padding: 0;
-  width: 32px;
-}
-
-.topbutton-bar button:active {
-  -webkit-box-shadow:
-    0 1px 0 0 #c2c2c2 inset,
-    0 0 0 1px #dedede inset;
-}
-
-.topbutton-bar button:hover,
-.topbutton-bar button:focus,
-.topbutton-bar button:active {
-  background-color: #ededed;
-}
-
-.topbutton-bar .maximize-button {
-  background-image: -webkit-image-set(
-      url(chrome://resources/images/apps/topbar_button_maximize.png) 1x,
-      url(chrome://resources/images/2x/apps/topbar_button_maximize.png) 2x);
-}
-
-.topbutton-bar .minimize-button {
-  background-image: -webkit-image-set(
-      url(chrome://resources/images/apps/topbar_button_minimize.png) 1x,
-      url(chrome://resources/images/2x/apps/topbar_button_minimize.png) 2x);
-}
-
-.topbutton-bar .close-button {
-  background-image: -webkit-image-set(
-      url(chrome://resources/images/apps/topbar_button_close.png) 1x,
-      url(chrome://resources/images/2x/apps/topbar_button_close.png) 2x);
-}
diff --git a/ui/webui/resources/images/2x/apps/topbar_button_close.png b/ui/webui/resources/images/2x/apps/topbar_button_close.png
deleted file mode 100644
index 7a28084..0000000
--- a/ui/webui/resources/images/2x/apps/topbar_button_close.png
+++ /dev/null
Binary files differ
diff --git a/ui/webui/resources/images/2x/apps/topbar_button_maximize.png b/ui/webui/resources/images/2x/apps/topbar_button_maximize.png
deleted file mode 100644
index 96cecc9..0000000
--- a/ui/webui/resources/images/2x/apps/topbar_button_maximize.png
+++ /dev/null
Binary files differ
diff --git a/ui/webui/resources/images/2x/apps/topbar_button_minimize.png b/ui/webui/resources/images/2x/apps/topbar_button_minimize.png
deleted file mode 100644
index 437c6f700..0000000
--- a/ui/webui/resources/images/2x/apps/topbar_button_minimize.png
+++ /dev/null
Binary files differ
diff --git a/ui/webui/resources/images/BUILD.gn b/ui/webui/resources/images/BUILD.gn
index 191c2ff..5691dcf 100644
--- a/ui/webui/resources/images/BUILD.gn
+++ b/ui/webui/resources/images/BUILD.gn
@@ -10,17 +10,6 @@
   out_grd = "$target_gen_dir/resources.grdp"
   input_files_base_dir = rebase_path(".", "//")
   input_files = [
-    # Component apps common image resources - 1x
-    "apps/topbar_button_close.png",
-    "apps/topbar_button_maximize.png",
-    "apps/topbar_button_minimize.png",
-
-    # Component apps common image resources - 2x
-    "2x/apps/topbar_button_close.png",
-    "2x/apps/topbar_button_maximize.png",
-    "2x/apps/topbar_button_minimize.png",
-
-    # Non-apps images
     "add.svg",
     "cancel_red.svg",
     "checkbox_black.png",
diff --git a/ui/webui/resources/images/apps/topbar_button_close.png b/ui/webui/resources/images/apps/topbar_button_close.png
deleted file mode 100644
index b902560..0000000
--- a/ui/webui/resources/images/apps/topbar_button_close.png
+++ /dev/null
Binary files differ
diff --git a/ui/webui/resources/images/apps/topbar_button_maximize.png b/ui/webui/resources/images/apps/topbar_button_maximize.png
deleted file mode 100644
index 7d45270..0000000
--- a/ui/webui/resources/images/apps/topbar_button_maximize.png
+++ /dev/null
Binary files differ
diff --git a/ui/webui/resources/images/apps/topbar_button_minimize.png b/ui/webui/resources/images/apps/topbar_button_minimize.png
deleted file mode 100644
index 33b892df..0000000
--- a/ui/webui/resources/images/apps/topbar_button_minimize.png
+++ /dev/null
Binary files differ
diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn
index 18f92816..0964bcb 100644
--- a/weblayer/browser/java/BUILD.gn
+++ b/weblayer/browser/java/BUILD.gn
@@ -183,8 +183,10 @@
     "org/chromium/weblayer_private/WebMessageReplyProxyImpl.java",
     "org/chromium/weblayer_private/WebShareServiceFactory.java",
     "org/chromium/weblayer_private/WebappsHelper.java",
+    "org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantBrowserControls.java",
     "org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantDependencies.java",
     "org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantStaticDependencies.java",
+    "org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantTabChangeObserver.java",
     "org/chromium/weblayer_private/bluetooth/WebLayerBluetoothChooserAndroidDelegate.java",
     "org/chromium/weblayer_private/bluetooth/WebLayerBluetoothScanningPromptAndroidDelegate.java",
     "org/chromium/weblayer_private/media/MediaRouteDialogFragmentImpl.java",
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
index c49a5862..3723120 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
@@ -63,6 +63,7 @@
 import org.chromium.ui.base.ViewAndroidDelegate;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.url.GURL;
+import org.chromium.weblayer_private.autofill_assistant.WebLayerAssistantTabChangeObserver;
 import org.chromium.weblayer_private.interfaces.APICallException;
 import org.chromium.weblayer_private.interfaces.IContextMenuParams;
 import org.chromium.weblayer_private.interfaces.IErrorPageCallbackClient;
@@ -152,6 +153,9 @@
 
     private WebLayerAccessibilityUtil.Observer mAccessibilityObserver;
 
+    private final WebLayerAssistantTabChangeObserver mWebLayerAssistantTabChangeObserver =
+            new WebLayerAssistantTabChangeObserver();
+
     private Set<FaviconCallbackProxy> mFaviconCallbackProxies = new HashSet<>();
 
     // Only non-null if scroll offsets have been requested.
@@ -354,7 +358,7 @@
      * Sets the BrowserImpl this TabImpl is contained in.
      */
     public void attachToBrowser(BrowserImpl browser) {
-        // NOTE: during tab creation this is called with |mBrowser| set to |browser|. This happens
+        // NOTE: during tab creation this is called with |browser| set to |mBrowser|. This happens
         // because the tab is created with |mBrowser| already set (to avoid having a bunch of null
         // checks).
         mBrowser = browser;
@@ -399,6 +403,8 @@
                         new AutofillActionModeCallback(mBrowser.getContext(), mAutofillProvider));
             }
         }
+
+        mWebLayerAssistantTabChangeObserver.onBrowserAttachmentChanged(mWebContents);
     }
 
     @VisibleForTesting
@@ -1001,6 +1007,8 @@
 
         TabImplJni.get().removeTabFromBrowserBeforeDestroying(mNativeTab);
 
+        mWebLayerAssistantTabChangeObserver.onTabDestroyed(mWebContents);
+
         // Notify the client that this instance is being destroyed to prevent it from calling
         // back into this object if the embedder mistakenly tries to do so.
         try {
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantBrowserControls.java b/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantBrowserControls.java
new file mode 100644
index 0000000..37e4f18
--- /dev/null
+++ b/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantBrowserControls.java
@@ -0,0 +1,55 @@
+
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.weblayer_private.autofill_assistant;
+
+import org.chromium.components.autofill_assistant.AssistantBrowserControls;
+
+/**
+ * Implementation of {@link AssistantBrowserControls} for WebLayer.
+ */
+public class WebLayerAssistantBrowserControls implements AssistantBrowserControls {
+    private AssistantBrowserControls.Observer mObserver;
+
+    @Override
+    public int getBottomControlsHeight() {
+        // TODO(b/222671580): Implement
+        return 0;
+    }
+
+    @Override
+    public int getBottomControlOffset() {
+        // TODO(b/222671580): Implement
+        return 0;
+    }
+
+    @Override
+    public int getContentOffset() {
+        // TODO(b/222671580): Implement
+        return 0;
+    }
+
+    @Override
+    public float getTopVisibleContentOffset() {
+        // TODO(b/222671580): Implement
+        return 0;
+    }
+
+    @Override
+    public void setObserver(AssistantBrowserControls.Observer browserControlsObserver) {
+        mObserver = browserControlsObserver;
+    }
+
+    @Override
+    public void destroy() {}
+
+    public void onControlsOffsetChanged() {
+        mObserver.onControlsOffsetChanged();
+    }
+
+    public void onBottomControlsHeightChanged() {
+        mObserver.onBottomControlsHeightChanged();
+    }
+}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantDependencies.java b/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantDependencies.java
index e984358..22786c01 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantDependencies.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantDependencies.java
@@ -27,8 +27,9 @@
  */
 public class WebLayerAssistantDependencies
         extends WebLayerAssistantStaticDependencies implements AssistantDependencies {
-    public WebLayerAssistantDependencies(WebContents webContents) {
-        super(webContents);
+    public WebLayerAssistantDependencies(WebContents webContents,
+            WebLayerAssistantTabChangeObserver webLayerAssistantTabChangeObserver) {
+        super(webContents, webLayerAssistantTabChangeObserver);
         maybeUpdateDependencies(webContents);
     }
 
@@ -103,13 +104,12 @@
 
     @Override
     public AssistantBrowserControlsFactory createBrowserControlsFactory() {
-        // TODO(b/222671580): Implement
-        return null;
+        return () -> new WebLayerAssistantBrowserControls();
     }
 
     @Override
     public Destroyable observeTabChanges(AssistantTabChangeObserver tabChangeObserver) {
-        // TODO(b/222671580): Implement
-        return null;
+        mWebLayerAssistantTabChangeObserver.addObserver(tabChangeObserver);
+        return () -> mWebLayerAssistantTabChangeObserver.removeObserver(tabChangeObserver);
     }
 }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantStaticDependencies.java b/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantStaticDependencies.java
index de9e45ae..d20ca076 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantStaticDependencies.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantStaticDependencies.java
@@ -44,9 +44,13 @@
 public class WebLayerAssistantStaticDependencies
         implements AssistantStaticDependencies, SimpleFactoryKeyHandle {
     protected final WebContents mWebContents;
+    protected final WebLayerAssistantTabChangeObserver mWebLayerAssistantTabChangeObserver;
 
-    WebLayerAssistantStaticDependencies(WebContents webContents) {
+    // There exists one instance of this class per WebContents and per TabImpl.
+    WebLayerAssistantStaticDependencies(WebContents webContents,
+            WebLayerAssistantTabChangeObserver webLayerAssistantTabChangeObserver) {
         mWebContents = webContents;
+        mWebLayerAssistantTabChangeObserver = webLayerAssistantTabChangeObserver;
     }
 
     // AssistantStaticDependencies implementation:
@@ -54,12 +58,13 @@
     @Override
     public long createNative() {
         return WebLayerAssistantStaticDependenciesJni.get().init(
-                new WebLayerAssistantStaticDependencies(mWebContents));
+                new WebLayerAssistantStaticDependencies(
+                        mWebContents, mWebLayerAssistantTabChangeObserver));
     }
 
     @Override
     public AssistantDependencies createDependencies(Activity activity) {
-        return new WebLayerAssistantDependencies(mWebContents);
+        return new WebLayerAssistantDependencies(mWebContents, mWebLayerAssistantTabChangeObserver);
     }
 
     @Override
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantTabChangeObserver.java b/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantTabChangeObserver.java
new file mode 100644
index 0000000..30663c0
--- /dev/null
+++ b/weblayer/browser/java/org/chromium/weblayer_private/autofill_assistant/WebLayerAssistantTabChangeObserver.java
@@ -0,0 +1,43 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.weblayer_private.autofill_assistant;
+
+import org.chromium.base.ObserverList;
+import org.chromium.components.autofill_assistant.AssistantTabChangeObserver;
+import org.chromium.content_public.browser.WebContents;
+
+/**
+ * Notifies of changes to a WebLayer tab.
+ * The functions onContentChanged and onWebContentsSwapped are never called on WebLayer since the
+ * tab never changes WebContents.
+ */
+public class WebLayerAssistantTabChangeObserver {
+    private final ObserverList<AssistantTabChangeObserver> mTabChangeObservers =
+            new ObserverList<AssistantTabChangeObserver>();
+
+    // TODO(b/222671580): onObservingDifferentTab
+    // TODO(b/222671580): onInteractabilityChanged
+
+    public void addObserver(AssistantTabChangeObserver tabChangeObserver) {
+        mTabChangeObservers.addObserver(tabChangeObserver);
+    }
+
+    public void removeObserver(AssistantTabChangeObserver tabChangeObserver) {
+        mTabChangeObservers.removeObserver(tabChangeObserver);
+    }
+
+    public void onBrowserAttachmentChanged(WebContents webContents) {
+        for (AssistantTabChangeObserver tabChangeObserver : mTabChangeObservers) {
+            tabChangeObserver.onActivityAttachmentChanged(
+                    webContents, webContents.getTopLevelNativeWindow());
+        }
+    }
+
+    public void onTabDestroyed(WebContents webContents) {
+        for (AssistantTabChangeObserver tabChangeObserver : mTabChangeObservers) {
+            tabChangeObserver.onDestroyed(webContents);
+        }
+    }
+}
diff --git a/weblayer/browser/signin_url_loader_throttle.cc b/weblayer/browser/signin_url_loader_throttle.cc
index a32816a..92919d5b 100644
--- a/weblayer/browser/signin_url_loader_throttle.cc
+++ b/weblayer/browser/signin_url_loader_throttle.cc
@@ -50,8 +50,7 @@
 void MaybeAddQueryParams(GURL* url) {
   // Add manage=true to query parameters for sign out URLs to make sure we
   // receive the Mirror response headers instead of the normal sign out page.
-  if (gaia::IsGaiaSignonRealm(url->DeprecatedGetOriginAsURL()) &&
-      url->path_piece() == kSignOutPath) {
+  if (gaia::HasGaiaSchemeHostPort(*url) && url->path_piece() == kSignOutPath) {
     *url = net::AppendOrReplaceQueryParameter(*url, "manage", "true");
   }
 }
@@ -163,8 +162,8 @@
 
 void SigninURLLoaderThrottle::ProcessResponse(
     const net::HttpResponseHeaders* headers) {
-  if (!gaia::IsGaiaSignonRealm(request_url_.DeprecatedGetOriginAsURL()) ||
-      !is_main_frame_ || !headers) {
+  if (!gaia::HasGaiaSchemeHostPort(request_url_) || !is_main_frame_ ||
+      !headers) {
     return;
   }