diff --git a/DEPS b/DEPS
index 757096d2..861d7c03 100644
--- a/DEPS
+++ b/DEPS
@@ -201,6 +201,13 @@
   # By default, do not check out versions of toolschains and sdks that are
   # specifically only needed by Lacros.
   'checkout_lacros_sdk': False,
+  # To update the sdk version:
+  # 1 Choose a version that's not newer than the Ash side so it's thoroughly
+  #   tested:
+  #   https://chromium-review.googlesource.com/q/%2522Automated+Commit:+LKGM%2522+status:merged
+  # 2 Run additional a few optional tryjobs:
+  #   lacros-amd64-generic-chrome-skylab
+  #   lacros-arm-generic-chrome-skylab
   'lacros_sdk_version': '14556.0.0',
 
   # Generate location tag metadata to include in tests result data uploaded
@@ -253,15 +260,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': '850de30a19f3e60dd7d766e07e60922709d2c21a',
+  'skia_revision': 'c35e492a19b047618dcea58043ba915ece6fc99d',
   # 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': '53958a11c7583d9e0e2eaaeb000ea418ae67efdd',
+  'v8_revision': '1e36a0692f526f9923d9e57e15e072287fe52950',
   # 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': 'cdcf1715304582b8fc92f7a073a8aa56014e64e0',
+  'angle_revision': '7d31a47fc7c367390bd8fda2ea6ab1e5819b7d6d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -269,7 +276,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'cfcefe544f79eaab65faa47bd59fdd96bbf41091',
+  'pdfium_revision': '3ae43ccd85e87861ceb2a02c0742fbe91305d58b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -300,7 +307,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': 'ed4d0710f14878b51ce1885e0f3221e2d6d97a5a',
+  'freetype_revision': '6fb7b7a09dfe348fefb16d163dc9d91f7503f1f6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -431,7 +438,7 @@
   'libcxx_revision':       '79a2e924d96e2fc1e4b937c42efd08898fa472d7',
 
   # GN CIPD package version.
-  'gn_version': 'git_revision:d18426e45644d2024370c389725b8334d43b85c7',
+  'gn_version': 'git_revision:ecec350e71ea4600f7bde967854e083fbc53a37f',
 }
 
 # Only these hosts are allowed for dependencies in this DEPS file.
@@ -720,7 +727,7 @@
     Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248',
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + 'b971684686a3b294dcb819193a5d7785ad99b21c',
+    'url': Var('chromium_git') + '/website.git' + '@' + 'e9c85f70dcafe55713d3507df0edb5dd0908970b',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -1106,7 +1113,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ff14b61068b1d0c6c58fa8ab0108d9476ca200e8',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '41c57603f9f598bf0e3fe50989dde5ba426532e1',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1677,7 +1684,7 @@
       'condition': 'checkout_android',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@e799ba9fb972c141daa6b0f3f7f820317e04c23d',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@1963b94c99e893de15b850c8b83c2fad614e1c17',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1713,10 +1720,10 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'cf04aebdf9b53bb2853f22a81465688daf879ec6',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '8f8ab3bf1d5d8ef722f041e52bb32172d25607ba',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '969db1ed93fc2d956f1fbbfe459e92e0f6fa36df',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'a92d051e0f4f3dcd4c43086a8f1edbbe5859235f',
+    Var('webrtc_git') + '/src.git' + '@' + '720aa9d5c782ddec09f18d301721eea70d77ad6b',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1786,7 +1793,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1540211a9d4a1bc8edf1863746fffe807b1c5609',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@cd83df06fc2667cb1b3224af7e5b55e09292fef3',
     'condition': 'checkout_src_internal',
   },
 
@@ -1827,7 +1834,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'AZc5cK_Jpknph6yWOLJBkz4dCAYhBiC39iHNSzocwCIC',
+        'version': 'BwkXdFEoWWIFmEdies-9qFIQgCOyWj22in9I2RbNRKkC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index 476d4bb..0db76f03 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -650,6 +650,7 @@
     "//android_webview/nonembedded:system_webview_manifest",
     "//android_webview/proto:metrics_bridge_records_proto_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/android_autofill/browser:java",
     "//components/autofill/android:autofill_java",
     "//components/background_task_scheduler:background_task_scheduler_task_ids_java",
@@ -788,6 +789,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//cc/base:cc_base_java",
     "//components/autofill/android:autofill_features_java",
     "//components/feature_engagement/public:public_java",
diff --git a/android_webview/glue/BUILD.gn b/android_webview/glue/BUILD.gn
index 83b3a8a..16fc109 100644
--- a/android_webview/glue/BUILD.gn
+++ b/android_webview/glue/BUILD.gn
@@ -16,6 +16,7 @@
     "//android_webview/support_library/boundary_interfaces:boundary_interface_java",
     "//android_webview/support_library/callback:callback_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/content_capture/android:java",
     "//components/embedder_support/android:application_java",
     "//components/embedder_support/android:util_java",
diff --git a/android_webview/js_sandbox/BUILD.gn b/android_webview/js_sandbox/BUILD.gn
index b23af3c..9026da73 100644
--- a/android_webview/js_sandbox/BUILD.gn
+++ b/android_webview/js_sandbox/BUILD.gn
@@ -33,6 +33,7 @@
     ":js_sandbox_jni_headers",
     "//base:base_java",
     "//base:jni_java",
+    "//build/android:build_java",
     "//third_party/android_deps:com_google_code_findbugs_jsr305_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
diff --git a/android_webview/nonembedded/BUILD.gn b/android_webview/nonembedded/BUILD.gn
index e691b7d..0d5f69aa 100644
--- a/android_webview/nonembedded/BUILD.gn
+++ b/android_webview/nonembedded/BUILD.gn
@@ -39,6 +39,7 @@
     "//android_webview/glue:glue_java",
     "//android_webview/proto:metrics_bridge_records_proto_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/about_ui/android:aboutui_java",
     "//components/crash/android:java",
     "//components/embedder_support/android:application_java",
diff --git a/android_webview/support_library/BUILD.gn b/android_webview/support_library/BUILD.gn
index 65cf647..d8a9f908 100644
--- a/android_webview/support_library/BUILD.gn
+++ b/android_webview/support_library/BUILD.gn
@@ -35,6 +35,7 @@
     "//android_webview/support_library/boundary_interfaces:boundary_interface_java",
     "//android_webview/support_library/callback:callback_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/embedder_support/android:util_java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn
index 3ecfe2b..9ee5e7c 100644
--- a/android_webview/test/BUILD.gn
+++ b/android_webview/test/BUILD.gn
@@ -92,6 +92,7 @@
     "//android_webview/js_sandbox:js_sandbox_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//components/android_autofill/browser/test_support:component_autofill_provider_java_test_support",
     "//components/content_capture/android/test_support:java",
     "//components/embedder_support/android:util_java",
@@ -231,6 +232,7 @@
     "//android_webview/test/embedded_test_server:aw_net_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//components/android_autofill/browser:java",
     "//components/android_autofill/browser/test_support:component_autofill_provider_java_test_support",
     "//components/autofill/android:autofill_java",
@@ -471,6 +473,7 @@
     "//android_webview/nonembedded:services_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//components/component_updater/android:component_provider_service_aidl_java",
     "//third_party/junit",
   ]
@@ -487,6 +490,7 @@
   deps = [
     "//android_webview:common_variations_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/component_updater/android:embedded_component_loader_java",
     "//components/variations/android:variations_java",
     "//third_party/junit",
@@ -623,6 +627,7 @@
   deps = [
     "//android_webview:android_webview_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/test/android:content_java_test_support",
   ]
   sources = [ "../unittestjava/src/org/chromium/android_webview/unittest/MockAwContentsClientBridge.java" ]
@@ -658,6 +663,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//components/component_updater/android:embedded_component_loader_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_deps:protobuf_lite_runtime_java",
diff --git a/android_webview/test/embedded_test_server/BUILD.gn b/android_webview/test/embedded_test_server/BUILD.gn
index e9807d7..0607800f 100644
--- a/android_webview/test/embedded_test_server/BUILD.gn
+++ b/android_webview/test/embedded_test_server/BUILD.gn
@@ -15,6 +15,7 @@
   deps = [
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//net/android:embedded_test_server_aidl_java",
     "//net/android:net_java",
     "//net/android:net_java_test_support",
@@ -67,6 +68,7 @@
   deps = [
     ":aw_net_java_test_support",
     "//base:base_java",
+    "//build/android:build_java",
   ]
   android_manifest = "java/AndroidManifest.xml"
   apk_name = "ChromiumNetTestAwSupport"
diff --git a/android_webview/tools/automated_ui_tests/BUILD.gn b/android_webview/tools/automated_ui_tests/BUILD.gn
index 33ea9ba..64966be 100644
--- a/android_webview/tools/automated_ui_tests/BUILD.gn
+++ b/android_webview/tools/automated_ui_tests/BUILD.gn
@@ -28,6 +28,7 @@
   deps = [
     ":webview_ui_test_app_apk_resources",
     "//base:base_java",
+    "//build/android:build_java",
   ]
 }
 
@@ -58,6 +59,7 @@
     ":webview_ui_test_app_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//third_party/android_deps:espresso_java",
     "//third_party/android_sdk:android_test_base_java",
     "//third_party/android_support_test_runner:rules_java",
diff --git a/android_webview/tools/system_webview_shell/BUILD.gn b/android_webview/tools/system_webview_shell/BUILD.gn
index ea387c6..b2f066c7 100644
--- a/android_webview/tools/system_webview_shell/BUILD.gn
+++ b/android_webview/tools/system_webview_shell/BUILD.gn
@@ -62,6 +62,7 @@
   deps = [
     ":system_webview_shell_apk_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/android_deps:guava_android_java",
     "//third_party/androidx:androidx_activity_activity_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
@@ -121,6 +122,7 @@
     ":system_webview_shell_apk_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_support_test_runner:rules_java",
@@ -144,6 +146,7 @@
     ":system_webview_shell_apk_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//third_party/android_sdk:android_test_base_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 4a421d8..564fa34 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1284,12 +1284,8 @@
     "system/network/fake_network_detailed_network_view.h",
     "system/network/fake_network_detailed_view_delegate.cc",
     "system/network/fake_network_detailed_view_delegate.h",
-    "system/network/fake_network_list_mobile_header_view.cc",
-    "system/network/fake_network_list_mobile_header_view.h",
     "system/network/fake_network_list_network_header_view_delegate.cc",
     "system/network/fake_network_list_network_header_view_delegate.h",
-    "system/network/fake_network_list_wifi_header_view.cc",
-    "system/network/fake_network_list_wifi_header_view.h",
     "system/network/network_detailed_network_view.cc",
     "system/network/network_detailed_network_view.h",
     "system/network/network_detailed_network_view_impl.cc",
@@ -1317,16 +1313,10 @@
     "system/network/network_info_bubble.h",
     "system/network/network_list_header_view.cc",
     "system/network/network_list_header_view.h",
-    "system/network/network_list_item_view.cc",
-    "system/network/network_list_item_view.h",
     "system/network/network_list_mobile_header_view.cc",
     "system/network/network_list_mobile_header_view.h",
-    "system/network/network_list_mobile_header_view_impl.cc",
-    "system/network/network_list_mobile_header_view_impl.h",
     "system/network/network_list_network_header_view.cc",
     "system/network/network_list_network_header_view.h",
-    "system/network/network_list_network_item_view.cc",
-    "system/network/network_list_network_item_view.h",
     "system/network/network_list_view.cc",
     "system/network/network_list_view.h",
     "system/network/network_list_view_controller.cc",
@@ -1335,8 +1325,6 @@
     "system/network/network_list_view_controller_impl.h",
     "system/network/network_list_wifi_header_view.cc",
     "system/network/network_list_wifi_header_view.h",
-    "system/network/network_list_wifi_header_view_impl.cc",
-    "system/network/network_list_wifi_header_view_impl.h",
     "system/network/network_observer.h",
     "system/network/network_row_title_view.cc",
     "system/network/network_row_title_view.h",
@@ -2726,7 +2714,6 @@
     "system/network/network_info_bubble_unittest.cc",
     "system/network/network_list_mobile_header_view_unittest.cc",
     "system/network/network_list_network_header_view_unittest.cc",
-    "system/network/network_list_network_item_view_unittest.cc",
     "system/network/network_list_view_controller_unittest.cc",
     "system/network/network_list_wifi_header_view_unittest.cc",
     "system/network/sms_observer_unittest.cc",
diff --git a/ash/app_list/views/apps_grid_view_unittest.cc b/ash/app_list/views/apps_grid_view_unittest.cc
index e3c88ff..a782403 100644
--- a/ash/app_list/views/apps_grid_view_unittest.cc
+++ b/ash/app_list/views/apps_grid_view_unittest.cc
@@ -5301,7 +5301,7 @@
   // Cache the current context menu view.
   views::MenuItemView* reorder_option =
       context_menu->root_menu_item_view()->GetSubmenu()->GetMenuItemAt(1);
-  ASSERT_TRUE(reorder_option->title() == u"Name");
+  ASSERT_EQ(reorder_option->title(), u"Name");
 
   // Open the Reorder by Name submenu.
   const gfx::Point reorder_option_point =
@@ -5317,7 +5317,7 @@
 
   reorder_option =
       context_menu->root_menu_item_view()->GetSubmenu()->GetMenuItemAt(2);
-  ASSERT_TRUE(reorder_option->title() == u"Color");
+  ASSERT_EQ(reorder_option->title(), u"Color");
 
   const gfx::Point color_option =
       reorder_option->GetBoundsInScreen().CenterPoint();
@@ -5349,7 +5349,7 @@
   // Cache the current context menu view.
   views::MenuItemView* reorder_submenu =
       context_menu->root_for_testing()->GetSubmenu()->GetMenuItemAt(2);
-  ASSERT_TRUE(reorder_submenu->title() == u"Sort by");
+  ASSERT_EQ(reorder_submenu->title(), u"Sort by");
 
   // Open the Sort by submenu.
   gfx::Point reorder_submenu_point =
@@ -5358,7 +5358,7 @@
 
   views::MenuItemView* reorder_option =
       reorder_submenu->GetSubmenu()->GetMenuItemAt(0);
-  ASSERT_TRUE(reorder_option->title() == u"Name");
+  ASSERT_EQ(reorder_option->title(), u"Name");
   gfx::Point reorder_option_point =
       reorder_option->GetBoundsInScreen().CenterPoint();
   SimulateLeftClickOrTapAt(reorder_option_point);
@@ -5378,14 +5378,14 @@
 
   reorder_submenu =
       context_menu->root_for_testing()->GetSubmenu()->GetMenuItemAt(2);
-  ASSERT_TRUE(reorder_submenu->title() == u"Sort by");
+  ASSERT_EQ(reorder_submenu->title(), u"Sort by");
 
   // Open the Sort by submenu.
   reorder_submenu_point = reorder_submenu->GetBoundsInScreen().CenterPoint();
   SimulateLeftClickOrTapAt(reorder_submenu_point);
 
   reorder_option = reorder_submenu->GetSubmenu()->GetMenuItemAt(1);
-  ASSERT_TRUE(reorder_option->title() == u"Color");
+  ASSERT_EQ(reorder_option->title(), u"Color");
   reorder_option_point = reorder_option->GetBoundsInScreen().CenterPoint();
   SimulateLeftClickOrTapAt(reorder_option_point);
 
@@ -5396,6 +5396,67 @@
       nullptr);
 }
 
+TEST_P(AppsGridViewAppSortTest,
+       NoSortOptionsWhenSearchPageIsShownInTabletMode) {
+  // This test checks the context menu on root window in tablet mode.
+  if (!create_as_tablet_mode_)
+    return;
+
+  model_->PopulateApps(1);
+  EXPECT_EQ(AppListSortOrder::kCustom, model_->requested_sort_order());
+
+  // Get a point in `apps_grid_view_` that doesn't have an item on it.
+  const gfx::Point empty_space =
+      apps_grid_view_->GetBoundsInScreen().CenterPoint();
+
+  // Open the menu to test the alphabetical sort option.
+  SimulateRightClickOrLongPressAt(empty_space);
+  AppMenuModelAdapter* context_menu =
+      Shell::GetPrimaryRootWindowController()->menu_model_adapter_for_testing();
+  EXPECT_TRUE(context_menu->IsShowingMenu());
+
+  // Cache the current context menu view.
+  views::MenuItemView* reorder_submenu =
+      context_menu->root_for_testing()->GetSubmenu()->GetMenuItemAt(2);
+  ASSERT_EQ(reorder_submenu->title(), u"Sort by");
+
+  // Open the Sort by submenu.
+  gfx::Point reorder_submenu_point =
+      reorder_submenu->GetBoundsInScreen().CenterPoint();
+  SimulateLeftClickOrTapAt(reorder_submenu_point);
+
+  views::MenuItemView* reorder_option =
+      reorder_submenu->GetSubmenu()->GetMenuItemAt(0);
+  ASSERT_EQ(reorder_option->title(), u"Name");
+  gfx::Point reorder_option_point =
+      reorder_option->GetBoundsInScreen().CenterPoint();
+  SimulateLeftClickOrTapAt(reorder_option_point);
+
+  // Check that the apps are sorted and the menu is closed.
+  EXPECT_EQ(AppListSortOrder::kNameAlphabetical,
+            model_->requested_sort_order());
+  EXPECT_EQ(
+      Shell::GetPrimaryRootWindowController()->menu_model_adapter_for_testing(),
+      nullptr);
+
+  // Activate the search box.
+  gfx::Point search_box_point =
+      search_box_view_->GetBoundsInScreen().CenterPoint();
+  SimulateLeftClickOrTapAt(search_box_point);
+
+  // Open the menu again.
+  SimulateRightClickOrLongPressAt(empty_space);
+  context_menu =
+      Shell::GetPrimaryRootWindowController()->menu_model_adapter_for_testing();
+  EXPECT_TRUE(context_menu->IsShowingMenu());
+
+  // Verify that the sort option is removed and there are only 2 options in the
+  // menu.
+  int context_menu_size =
+      context_menu->root_for_testing()->GetSubmenu()->GetMenuItems().size();
+  EXPECT_LT(context_menu_size, 3);
+}
+
 TEST_P(AppsGridViewAppSortTest, ContextMenuOnFolderItemSortAllApps) {
   // In this test, the sort algorithm is not tested. Instead, the context menu
   // that contains the options to sort is verified to be shown on folder app
@@ -5424,7 +5485,7 @@
   // Cache the current context menu view.
   views::MenuItemView* reorder_option =
       context_menu->root_menu_item_view()->GetSubmenu()->GetMenuItemAt(1);
-  ASSERT_TRUE(reorder_option->title() == u"Name");
+  ASSERT_EQ(reorder_option->title(), u"Name");
 
   // Open the Reorder by Name submenu.
   gfx::Point reorder_option_point =
@@ -5440,7 +5501,7 @@
 
   reorder_option =
       context_menu->root_menu_item_view()->GetSubmenu()->GetMenuItemAt(2);
-  ASSERT_TRUE(reorder_option->title() == u"Color");
+  ASSERT_EQ(reorder_option->title(), u"Color");
 
   const gfx::Point color_option =
       reorder_option->GetBoundsInScreen().CenterPoint();
diff --git a/ash/capture_mode/capture_mode_camera_preview_view.cc b/ash/capture_mode/capture_mode_camera_preview_view.cc
index 47cacd9..43bb7ee 100644
--- a/ash/capture_mode/capture_mode_camera_preview_view.cc
+++ b/ash/capture_mode/capture_mode_camera_preview_view.cc
@@ -260,6 +260,10 @@
   DCHECK_EQ(width(), height());
   camera_video_renderer_.host_window()->layer()->SetRoundedCornerRadius(
       gfx::RoundedCornersF(height() / 2.f));
+
+  // Refocus the camera preview to relayout the focus ring on it.
+  if (has_focus())
+    PseudoFocus();
 }
 
 void CameraPreviewView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 391bea6..4c59166 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -1111,7 +1111,7 @@
 // Enables the Camera Roll feature in Phone Hub, which allows users to access
 // recent photos and videos taken on a connected Android device
 const base::Feature kPhoneHubCameraRoll{"PhoneHubCameraRoll",
-                                        base::FEATURE_DISABLED_BY_DEFAULT};
+                                        base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enables the incoming/ongoing call notification feature in Phone Hub.
 const base::Feature kPhoneHubCallNotification{
diff --git a/ash/drag_drop/tab_drag_drop_delegate.cc b/ash/drag_drop/tab_drag_drop_delegate.cc
index ef6f5bec..ad06a46 100644
--- a/ash/drag_drop/tab_drag_drop_delegate.cc
+++ b/ash/drag_drop/tab_drag_drop_delegate.cc
@@ -127,7 +127,7 @@
       screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
           root_window_);
 
-  const SplitViewController::SnapPosition snap_position =
+  SplitViewController::SnapPosition snap_position =
       ::ash::GetSnapPositionForLocation(
           Shell::GetPrimaryRootWindow(), location_in_screen,
           start_location_in_screen_,
@@ -139,6 +139,9 @@
           /*vertical_edge_inset=*/area.height() *
                   kHighlightScreenPrimaryAxisRatio +
               kHighlightScreenEdgePaddingDp);
+  if (ShouldPreventSnapToTheEdge(location_in_screen))
+    snap_position = SplitViewController::SnapPosition::NONE;
+
   split_view_drag_indicators_->SetWindowDraggingState(
       SplitViewDragIndicators::ComputeWindowDraggingState(
           true, SplitViewDragIndicators::WindowDraggingState::kFromTop,
@@ -190,6 +193,8 @@
           /*vertical_edge_inset=*/area.height() *
                   kHighlightScreenPrimaryAxisRatio +
               kHighlightScreenEdgePaddingDp);
+  if (ShouldPreventSnapToTheEdge(location_in_screen))
+    snap_position_in_snapping_zone = SplitViewController::SnapPosition::NONE;
 
   if (snap_position_in_snapping_zone == SplitViewController::SnapPosition::NONE)
     RestoreSourceWindowBounds();
@@ -251,6 +256,16 @@
   split_view_controller->SnapWindow(source_window_, opposite_position);
 }
 
+bool TabDragDropDelegate::ShouldPreventSnapToTheEdge(
+    const gfx::Point& location_in_screen) {
+  SplitViewController* const split_view_controller =
+      SplitViewController::Get(source_window_);
+  return !split_view_controller->InSplitViewMode() &&
+         split_view_controller->IsLayoutHorizontal(source_window_) &&
+         location_in_screen.y() <
+             Shell::Get()->shell_delegate()->GetBrowserWebUITabStripHeight();
+}
+
 void TabDragDropDelegate::UpdateSourceWindowBoundsIfNecessary(
     SplitViewController::SnapPosition candidate_snap_position,
     const gfx::Point& location_in_screen) {
diff --git a/ash/drag_drop/tab_drag_drop_delegate.h b/ash/drag_drop/tab_drag_drop_delegate.h
index 73cf9ca3..22254fb4 100644
--- a/ash/drag_drop/tab_drag_drop_delegate.h
+++ b/ash/drag_drop/tab_drag_drop_delegate.h
@@ -76,6 +76,23 @@
   void OnNewBrowserWindowCreated(const gfx::Point& location_in_screen,
                                  aura::Window* new_window);
 
+  // This method returns true when all of the conditions below are met
+  //
+  // - Not in split view mode
+  // - In landscape mode
+  // - The current drag location is inside the WebUI tab strip
+  //
+  // When it returns true, we don't allow to enter split view because
+  // it hinders dragging tabs within the tab strip to trigger auto-scroll.
+  // This restriction does not apply to split screen mode because either
+  // the left/right could be non browser window, which may lead to
+  // confusing behavior.
+  // It also does not apply to portrait mode because dragging up/down to
+  // enter split screen does not hinder dragging left/right to move tabs.
+  //
+  // https://crbug.com/1316070
+  bool ShouldPreventSnapToTheEdge(const gfx::Point& location_in_screen);
+
   aura::Window* const root_window_;
   aura::Window* const source_window_;
   const gfx::Point start_location_in_screen_;
diff --git a/ash/drag_drop/tab_drag_drop_delegate_unittest.cc b/ash/drag_drop/tab_drag_drop_delegate_unittest.cc
index 83f7ccb..ea9726e 100644
--- a/ash/drag_drop/tab_drag_drop_delegate_unittest.cc
+++ b/ash/drag_drop/tab_drag_drop_delegate_unittest.cc
@@ -43,12 +43,16 @@
 
 namespace {
 
+constexpr int kWebUITabStripHeight = 100;
+
 class MockShellDelegate : public TestShellDelegate {
  public:
   MockShellDelegate() = default;
   ~MockShellDelegate() override = default;
 
   MOCK_METHOD(bool, IsTabDrag, (const ui::OSExchangeData&), (override));
+
+  int GetBrowserWebUITabStripHeight() override { return kWebUITabStripHeight; }
 };
 
 class MockNewWindowDelegate : public TestNewWindowDelegate {
@@ -179,6 +183,8 @@
       SplitViewController::Get(source_window.get())->InTabletSplitViewMode());
 }
 
+// When a tab is dragged to the left/right side of the Web Contents. It should
+// enter split view.
 TEST_F(TabDragDropDelegateTest, DropOnEdgeEntersSplitView) {
   // Create the source window. This should automatically fill the work area
   // since we're in tablet mode.
@@ -219,6 +225,44 @@
                                      SplitViewController::SnapPosition::LEFT));
 }
 
+// When a tab is dragged to the left/right edge of the tab strip. It should not
+// enter split view.
+// https://crbug.com/1316070
+TEST_F(TabDragDropDelegateTest, DropOnEdgeShouldNotEnterSplitView) {
+  // Create the source window. This should automatically fill the work area
+  // since we're in tablet mode.
+  std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
+
+  // We want to avoid entering overview mode between the delegate.Drop()
+  // call and |new_window|'s destruction. So we define it here before
+  // creating it.
+  std::unique_ptr<aura::Window> new_window;
+
+  // Emulate a drag to the right edge of the tab strip. It should not enter
+  // split view.
+  const gfx::Point drag_start_location = source_window->bounds().CenterPoint();
+  const gfx::Point drag_end_location =
+      gfx::Point(source_window->bounds().right(), kWebUITabStripHeight * 0.5);
+
+  auto delegate = std::make_unique<TabDragDropDelegate>(
+      Shell::GetPrimaryRootWindow(), source_window.get(), drag_start_location);
+  delegate->DragUpdate(drag_start_location);
+  delegate->DragUpdate(drag_end_location);
+
+  new_window = CreateToplevelTestWindow();
+  EXPECT_CALL(*mock_new_window_delegate(),
+              NewWindowForDetachingTab(source_window.get(), _, _))
+      .Times(1)
+      .WillOnce(RunOnceCallback<2>(new_window.get()));
+
+  delegate.release()->DropAndDeleteSelf(drag_end_location,
+                                        ui::OSExchangeData());
+
+  SplitViewController* const split_view_controller =
+      SplitViewController::Get(source_window.get());
+  EXPECT_FALSE(split_view_controller->InTabletSplitViewMode());
+}
+
 TEST_F(TabDragDropDelegateTest, DropTabInSplitViewMode) {
   // Enter tablet split view mode by snap the source window to the left.
   std::unique_ptr<aura::Window> source_window = CreateToplevelTestWindow();
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index ae692c7..e5f4dc6 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -37,6 +37,7 @@
 #include "ash/metrics/user_metrics_recorder.h"
 #include "ash/public/cpp/child_accounts/parent_access_controller.h"
 #include "ash/public/cpp/login_accelerators.h"
+#include "ash/public/cpp/login_types.h"
 #include "ash/public/cpp/smartlock_state.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/session/session_controller_impl.h"
@@ -696,6 +697,16 @@
   OnLockScreenNoteStateChanged(initial_note_action_state);
   chromeos::PowerManagerClient::Get()->AddObserver(this);
   RegisterAccelerators();
+
+  // If feature is enabled, update the boolean kiosk_license_mode_. Otherwise,
+  // it's false by default.
+  if (features::IsKioskEnrollmentInOobeEnabled()) {
+    kiosk_license_mode_ =
+        Shell::Get()
+            ->system_tray_model()
+            ->enterprise_domain()
+            ->management_device_mode() == ManagementDeviceMode::kKioskSku;
+  }
 }
 
 LockContentsView::~LockContentsView() {
@@ -962,7 +973,6 @@
   main_layout->set_cross_axis_alignment(
       views::BoxLayout::CrossAxisAlignment::kCenter);
 
-  // TODO(crbug.com/1307303): Determine if this is a kiosk license device.
   if (kiosk_license_mode_)
     return;
 
diff --git a/ash/public/cpp/system/toast_catalog.h b/ash/public/cpp/system/toast_catalog.h
index ef8a018..a1de17e 100644
--- a/ash/public/cpp/system/toast_catalog.h
+++ b/ash/public/cpp/system/toast_catalog.h
@@ -45,7 +45,8 @@
   kExtensionInstallSuccess = 31,
   kAccountRemoved = 32,
   kDeskTemplateTooLarge = 33,
-  kMaxValue = kDeskTemplateTooLarge,
+  kUndoCloseAll = 34,
+  kMaxValue = kUndoCloseAll,
 };
 
 }  // namespace ash
diff --git a/ash/public/cpp/system/toast_data.h b/ash/public/cpp/system/toast_data.h
index 93513c7..6875088 100644
--- a/ash/public/cpp/system/toast_data.h
+++ b/ash/public/cpp/system/toast_data.h
@@ -54,6 +54,7 @@
   std::u16string dismiss_text;
   bool is_managed = false;
   base::RepeatingClosure dismiss_callback;
+  base::RepeatingClosure expired_callback;
   base::TimeTicks time_created;
 };
 
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index e5e4b7b..7c43612 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -794,8 +794,11 @@
   // Appends the apps sort options in ShelfContextMenuModel in tablet mode. Note
   // that the launcher UI is fullscreen in tablet mode, so the whole root window
   // can be perceived by users to be part of the launcher.
+  auto* const app_list_controller = Shell::Get()->app_list_controller();
   if (features::IsLauncherAppSortEnabled() && tablet_mode &&
-      Shell::Get()->app_list_controller()->IsVisible(display_id)) {
+      app_list_controller->IsVisible(display_id) &&
+      app_list_controller->GetCurrentAppListPage() ==
+          AppListState::kStateApps) {
     ui::SimpleMenuModel* menu_model = root_window_menu_model_adapter_->model();
     sort_apps_submenu_ = std::make_unique<ui::SimpleMenuModel>(
         static_cast<ShelfContextMenuModel*>(menu_model));
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc
index d0ad0f4..97e6e73 100644
--- a/ash/shelf/login_shelf_view.cc
+++ b/ash/shelf/login_shelf_view.cc
@@ -19,6 +19,7 @@
 #include "ash/metrics/login_metrics_recorder.h"
 #include "ash/metrics/user_metrics_recorder.h"
 #include "ash/public/cpp/login_accelerators.h"
+#include "ash/public/cpp/login_types.h"
 #include "ash/public/cpp/shelf_config.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/root_window_controller.h"
@@ -33,6 +34,8 @@
 #include "ash/style/default_color_constants.h"
 #include "ash/style/default_colors.h"
 #include "ash/style/style_util.h"
+#include "ash/system/model/enterprise_domain_model.h"
+#include "ash/system/model/system_tray_model.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/system/status_area_widget_delegate.h"
 #include "ash/system/tray/system_tray_notifier.h"
@@ -653,6 +656,16 @@
       lock_screen_action_background);
   login_data_dispatcher_observation_.Observe(
       Shell::Get()->login_screen_controller()->data_dispatcher());
+
+  // If feature is enabled, update the boolean kiosk_license_mode_. Otherwise,
+  // it's false by default.
+  if (features::IsKioskEnrollmentInOobeEnabled()) {
+    kiosk_license_mode_ =
+        Shell::Get()
+            ->system_tray_model()
+            ->enterprise_domain()
+            ->management_device_mode() == ManagementDeviceMode::kKioskSku;
+  }
   UpdateUi();
 }
 
diff --git a/ash/system/network/fake_network_detailed_network_view.cc b/ash/system/network/fake_network_detailed_network_view.cc
index 4cc8cc77..c115ebe 100644
--- a/ash/system/network/fake_network_detailed_network_view.cc
+++ b/ash/system/network/fake_network_detailed_network_view.cc
@@ -5,7 +5,6 @@
 #include "ash/system/network/fake_network_detailed_network_view.h"
 
 #include "ash/system/network/network_detailed_network_view.h"
-#include "ash/system/network/network_list_item_view.h"
 
 namespace ash {
 
@@ -19,8 +18,4 @@
   return this;
 }
 
-void FakeNetworkDetailedNetworkView::OnViewClicked(views::View* view) {
-  last_clicked_network_list_item_ = static_cast<NetworkListItemView*>(view);
-}
-
 }  // namespace ash
\ No newline at end of file
diff --git a/ash/system/network/fake_network_detailed_network_view.h b/ash/system/network/fake_network_detailed_network_view.h
index b732e3a3..4f09719 100644
--- a/ash/system/network/fake_network_detailed_network_view.h
+++ b/ash/system/network/fake_network_detailed_network_view.h
@@ -7,7 +7,6 @@
 
 #include "ash/ash_export.h"
 #include "ash/system/network/network_detailed_network_view.h"
-#include "ash/system/network/network_list_item_view.h"
 #include "ui/views/view.h"
 
 namespace ash {
@@ -15,8 +14,7 @@
 // Fake implementation of NetworkDetailedNetworkView.
 class ASH_EXPORT FakeNetworkDetailedNetworkView
     : public NetworkDetailedNetworkView,
-      public views::View,
-      public ViewClickListener {
+      public views::View {
  public:
   explicit FakeNetworkDetailedNetworkView(Delegate* delegate);
   FakeNetworkDetailedNetworkView(const FakeNetworkDetailedNetworkView&) =
@@ -25,18 +23,9 @@
       const FakeNetworkDetailedNetworkView&) = delete;
   ~FakeNetworkDetailedNetworkView() override;
 
-  const NetworkListItemView* last_clicked_network_list_item() const {
-    return last_clicked_network_list_item_;
-  }
-
  private:
   // NetworkDetailedNetworkView:
   views::View* GetAsView() override;
-
-  // ViewClickListener:
-  void OnViewClicked(views::View* view) override;
-
-  NetworkListItemView* last_clicked_network_list_item_ = nullptr;
 };
 
 }  // namespace ash
diff --git a/ash/system/network/fake_network_list_mobile_header_view.cc b/ash/system/network/fake_network_list_mobile_header_view.cc
deleted file mode 100644
index 4111c96..0000000
--- a/ash/system/network/fake_network_list_mobile_header_view.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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 "ash/system/network/fake_network_list_mobile_header_view.h"
-
-#include "ash/system/network/network_list_mobile_header_view.h"
-#include "ash/system/network/network_list_network_header_view.h"
-
-namespace ash {
-
-FakeNetworkListMobileHeaderView::FakeNetworkListMobileHeaderView(
-    NetworkListNetworkHeaderView::Delegate* delegate)
-    : NetworkListMobileHeaderView(delegate) {}
-
-FakeNetworkListMobileHeaderView::~FakeNetworkListMobileHeaderView() = default;
-
-void FakeNetworkListMobileHeaderView::SetToggleState(bool enabled,
-                                                     bool visible) {
-  is_toggle_enabled_ = enabled;
-  is_toggle_visible_ = visible;
-  set_toggle_state_count_++;
-};
-
-void FakeNetworkListMobileHeaderView::SetAddESimButtonState(bool enabled,
-                                                            bool visible) {
-  is_add_esim_enabled_ = enabled;
-  is_add_esim_visible_ = visible;
-  set_add_esim_button_state_count_++;
-};
-
-}  // namespace ash
\ No newline at end of file
diff --git a/ash/system/network/fake_network_list_mobile_header_view.h b/ash/system/network/fake_network_list_mobile_header_view.h
deleted file mode 100644
index d8dcbde..0000000
--- a/ash/system/network/fake_network_list_mobile_header_view.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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 ASH_SYSTEM_NETWORK_FAKE_NETWORK_LIST_MOBILE_HEADER_VIEW_H_
-#define ASH_SYSTEM_NETWORK_FAKE_NETWORK_LIST_MOBILE_HEADER_VIEW_H_
-
-#include "ash/ash_export.h"
-#include "ash/style/icon_button.h"
-#include "ash/system/network/network_list_mobile_header_view.h"
-#include "ash/system/network/network_list_network_header_view.h"
-#include "ash/system/tray/tri_view.h"
-
-namespace ash {
-
-// Fake implementation of NetworkListMobileHeaderView
-class ASH_EXPORT FakeNetworkListMobileHeaderView
-    : public NetworkListMobileHeaderView {
- public:
-  explicit FakeNetworkListMobileHeaderView(
-      NetworkListNetworkHeaderView::Delegate* delegate);
-  FakeNetworkListMobileHeaderView(const FakeNetworkListMobileHeaderView&) =
-      delete;
-  FakeNetworkListMobileHeaderView& operator=(
-      const FakeNetworkListMobileHeaderView&) = delete;
-  ~FakeNetworkListMobileHeaderView() override;
-
-  bool is_toggle_enabled() { return is_toggle_enabled_; }
-
-  bool is_toggle_visible() { return is_toggle_visible_; }
-
-  size_t set_toggle_state_count() { return set_toggle_state_count_; }
-
-  bool is_add_esim_enabled() { return is_add_esim_enabled_; }
-
-  bool is_add_esim_visible() { return is_add_esim_visible_; }
-
-  size_t set_add_esim_button_state_count() {
-    return set_add_esim_button_state_count_;
-  }
-
- private:
-  // NetworkListNetworkHeaderView:
-  void SetToggleState(bool enabled, bool visible) override;
-
-  // NetworkListMobileHeaderView:
-  void SetAddESimButtonState(bool enabled, bool visible) override;
-
-  bool is_toggle_enabled_;
-  bool is_toggle_visible_;
-  size_t set_toggle_state_count_;
-
-  bool is_add_esim_enabled_;
-  bool is_add_esim_visible_;
-  size_t set_add_esim_button_state_count_;
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_NETWORK_FAKE_NETWORK_LIST_MOBIL_HEADER_VIEW_H_
diff --git a/ash/system/network/fake_network_list_wifi_header_view.cc b/ash/system/network/fake_network_list_wifi_header_view.cc
deleted file mode 100644
index a0a91d8..0000000
--- a/ash/system/network/fake_network_list_wifi_header_view.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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 "ash/system/network/fake_network_list_wifi_header_view.h"
-
-#include "ash/system/network/network_list_network_header_view.h"
-#include "ash/system/network/network_list_wifi_header_view.h"
-
-namespace ash {
-
-FakeNetworkListWifiHeaderView::FakeNetworkListWifiHeaderView(
-    NetworkListNetworkHeaderView::Delegate* delegate)
-    : NetworkListWifiHeaderView(delegate) {}
-
-FakeNetworkListWifiHeaderView::~FakeNetworkListWifiHeaderView() = default;
-
-void FakeNetworkListWifiHeaderView::SetToggleState(bool enabled, bool visible) {
-  is_toggle_enabled_ = enabled;
-  is_toggle_visible_ = visible;
-  set_toggle_state_count_++;
-};
-
-void FakeNetworkListWifiHeaderView::SetJoinWifiButtonState(bool enabled,
-                                                           bool visible) {
-  is_join_wifi_enabled_ = enabled;
-  is_join_wifi_visible_ = visible;
-  set_join_wifi_button_state_count_++;
-};
-
-}  // namespace ash
\ No newline at end of file
diff --git a/ash/system/network/fake_network_list_wifi_header_view.h b/ash/system/network/fake_network_list_wifi_header_view.h
deleted file mode 100644
index 7fc1c9a8e..0000000
--- a/ash/system/network/fake_network_list_wifi_header_view.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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 ASH_SYSTEM_NETWORK_FAKE_NETWORK_LIST_WIFI_HEADER_VIEW_H_
-#define ASH_SYSTEM_NETWORK_FAKE_NETWORK_LIST_WIFI_HEADER_VIEW_H_
-
-#include "ash/ash_export.h"
-#include "ash/style/icon_button.h"
-#include "ash/system/network/network_list_network_header_view.h"
-#include "ash/system/network/network_list_wifi_header_view.h"
-#include "ash/system/tray/tri_view.h"
-
-namespace ash {
-
-// Fake implementation of NetworkListWifiHeaderView
-class ASH_EXPORT FakeNetworkListWifiHeaderView
-    : public NetworkListWifiHeaderView {
- public:
-  explicit FakeNetworkListWifiHeaderView(
-      NetworkListNetworkHeaderView::Delegate* delegate);
-  FakeNetworkListWifiHeaderView(const FakeNetworkListWifiHeaderView&) = delete;
-  FakeNetworkListWifiHeaderView& operator=(
-      const FakeNetworkListWifiHeaderView&) = delete;
-  ~FakeNetworkListWifiHeaderView() override;
-
-  bool is_toggle_enabled() { return is_toggle_enabled_; }
-
-  bool is_toggle_visible() { return is_toggle_visible_; }
-
-  size_t set_toggle_state_count() { return set_toggle_state_count_; }
-
-  bool is_join_wifi_enabled() { return is_join_wifi_enabled_; }
-
-  bool is_join_wifi_visible() { return is_join_wifi_visible_; }
-
-  size_t set_join_wifi_button_state_count() {
-    return set_join_wifi_button_state_count_;
-  }
-
- private:
-  // NetworkListNetworkHeaderView:
-  void SetToggleState(bool enabled, bool visible) override;
-
-  // NetworkListWifiHeaderView:
-  void SetJoinWifiButtonState(bool enabled, bool visible) override;
-
-  bool is_toggle_enabled_;
-  bool is_toggle_visible_;
-  size_t set_toggle_state_count_;
-
-  bool is_join_wifi_enabled_;
-  bool is_join_wifi_visible_;
-  size_t set_join_wifi_button_state_count_;
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_NETWORK_FAKE_NETWORK_LIST_WIFI_HEADER_VIEW_H_
diff --git a/ash/system/network/network_list_item_view.cc b/ash/system/network/network_list_item_view.cc
deleted file mode 100644
index df23a8d..0000000
--- a/ash/system/network/network_list_item_view.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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 "ash/system/network/network_list_item_view.h"
-
-#include <string>
-
-#include "ash/constants/ash_features.h"
-#include "ash/strings/grit/ash_strings.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/metadata/metadata_impl_macros.h"
-
-namespace ash {
-
-namespace {
-using chromeos::network_config::mojom::ActivationStateType;
-using chromeos::network_config::mojom::NetworkType;
-}  // namespace
-
-NetworkListItemView::NetworkListItemView(ViewClickListener* listener)
-    : HoverHighlightView(listener) {
-  DCHECK(ash::features::IsQuickSettingsNetworkRevampEnabled());
-}
-
-NetworkListItemView::~NetworkListItemView() = default;
-
-std::u16string NetworkListItemView::GetLabel() {
-  if (network_properties_->type == NetworkType::kCellular) {
-    ActivationStateType activation_state =
-        network_properties_->type_state->get_cellular()->activation_state;
-    if (activation_state == ActivationStateType::kActivating) {
-      return l10n_util::GetStringFUTF16(
-          IDS_ASH_STATUS_TRAY_NETWORK_LIST_ACTIVATING,
-          base::UTF8ToUTF16(network_properties_->name));
-    }
-    if (activation_state == ActivationStateType::kNotActivated ||
-        activation_state == ActivationStateType::kPartiallyActivated) {
-      return base::UTF8ToUTF16(network_properties_->name);
-    }
-  }
-  // Otherwise just show the network name or 'Ethernet'.
-  if (network_properties_->type == NetworkType::kEthernet)
-    return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ETHERNET);
-  return base::UTF8ToUTF16(network_properties_->name);
-}
-
-BEGIN_METADATA(NetworkListItemView, HoverHighlightView)
-END_METADATA
-
-}  // namespace ash
\ No newline at end of file
diff --git a/ash/system/network/network_list_item_view.h b/ash/system/network/network_list_item_view.h
deleted file mode 100644
index 0f911c54..0000000
--- a/ash/system/network/network_list_item_view.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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 ASH_SYSTEM_NETWORK_NETWORK_LIST_ITEM_VIEW_H_
-#define ASH_SYSTEM_NETWORK_NETWORK_LIST_ITEM_VIEW_H_
-
-#include "ash/ash_export.h"
-#include "ash/system/network/network_info.h"
-#include "ash/system/tray/hover_highlight_view.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
-#include "ui/base/metadata/metadata_impl_macros.h"
-
-namespace ash {
-
-class ViewClickListener;
-
-// Base class used in configuring the view shown for a single network in
-// the detailed Network page within the quick settings.
-class ASH_EXPORT NetworkListItemView : public HoverHighlightView {
- public:
-  METADATA_HEADER(NetworkListItemView);
-
-  NetworkListItemView(const NetworkListItemView&) = delete;
-  NetworkListItemView& operator=(const NetworkListItemView&) = delete;
-  ~NetworkListItemView() override;
-
-  virtual void UpdateViewForNetwork(
-      const chromeos::network_config::mojom::NetworkStatePropertiesPtr&
-          network_properties) = 0;
-
-  const chromeos::network_config::mojom::NetworkStatePropertiesPtr&
-  network_properties() {
-    return network_properties_;
-  }
-
- protected:
-  explicit NetworkListItemView(ViewClickListener* listener);
-
-  std::u16string GetLabel();
-
-  chromeos::network_config::mojom::NetworkStatePropertiesPtr
-      network_properties_;
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_NETWORK_NETWORK_LIST_ITEM_VIEW_H_
\ No newline at end of file
diff --git a/ash/system/network/network_list_mobile_header_view.cc b/ash/system/network/network_list_mobile_header_view.cc
index 75e497ac..e1db8f29 100644
--- a/ash/system/network/network_list_mobile_header_view.cc
+++ b/ash/system/network/network_list_mobile_header_view.cc
@@ -4,16 +4,105 @@
 
 #include "ash/system/network/network_list_mobile_header_view.h"
 
+#include "ash/ash_export.h"
+#include "ash/constants/ash_features.h"
+#include "ash/public/cpp/system_tray_client.h"
+#include "ash/resources/vector_icons/vector_icons.h"
+#include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
+#include "ash/style/icon_button.h"
+#include "ash/system/model/system_tray_model.h"
 #include "ash/system/network/network_list_network_header_view.h"
+#include "ash/system/network/tray_network_state_model.h"
+#include "ash/system/tray/tray_popup_utils.h"
+#include "ash/system/tray/tri_view.h"
+#include "base/memory/weak_ptr.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
+#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "components/onc/onc_constants.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/view.h"
 
 namespace ash {
+namespace {
+
+using chromeos::network_config::mojom::DeviceStateProperties;
+using chromeos::network_config::mojom::DeviceStateType;
+using chromeos::network_config::mojom::NetworkType;
+
+int GetAddESimTooltipMessageId() {
+  const DeviceStateProperties* cellular_device =
+      Shell::Get()->system_tray_model()->network_state_model()->GetDevice(
+          NetworkType::kCellular);
+  if (!cellular_device)
+    return 0;
+
+  switch (cellular_device->inhibit_reason) {
+    case chromeos::network_config::mojom::InhibitReason::kInstallingProfile:
+      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_INSTALLING_PROFILE;
+    case chromeos::network_config::mojom::InhibitReason::kRenamingProfile:
+      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_RENAMING_PROFILE;
+    case chromeos::network_config::mojom::InhibitReason::kRemovingProfile:
+      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_REMOVING_PROFILE;
+    case chromeos::network_config::mojom::InhibitReason::kConnectingToProfile:
+      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_CONNECTING_TO_PROFILE;
+    case chromeos::network_config::mojom::InhibitReason::kRefreshingProfileList:
+      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_REFRESHING_PROFILE_LIST;
+    case chromeos::network_config::mojom::InhibitReason::kNotInhibited:
+      return IDS_ASH_STATUS_TRAY_ADD_CELLULAR_LABEL;
+    case chromeos::network_config::mojom::InhibitReason::kResettingEuiccMemory:
+      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_RESETTING_ESIM;
+    case chromeos::network_config::mojom::InhibitReason::kDisablingProfile:
+      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_DISABLING_PROFILE;
+  }
+}
+
+}  // namespace
 
 NetworkListMobileHeaderView::NetworkListMobileHeaderView(
     NetworkListNetworkHeaderView::Delegate* delegate)
     : NetworkListNetworkHeaderView(delegate,
-                                   IDS_ASH_STATUS_TRAY_NETWORK_MOBILE) {}
+                                   IDS_ASH_STATUS_TRAY_NETWORK_MOBILE) {
+  AddExtraButtons();
+}
 
 NetworkListMobileHeaderView::~NetworkListMobileHeaderView() = default;
 
+void NetworkListMobileHeaderView::AddExtraButtons() {
+  // The button navigates to Settings, only add it if this can occur.
+  if (!TrayPopupUtils::CanOpenWebUISettings())
+    return;
+
+  const gfx::VectorIcon& icon = base::i18n::IsRTL() ? kAddCellularNetworkRtlIcon
+                                                    : kAddCellularNetworkIcon;
+  std::unique_ptr<IconButton> add_esim_button = std::make_unique<IconButton>(
+      base::BindRepeating(&NetworkListMobileHeaderView::AddESimButtonPressed,
+                          weak_factory_.GetWeakPtr()),
+      IconButton::Type::kSmall, &icon, GetAddESimTooltipMessageId());
+  add_esim_button.get()->SetID(kAddESimButtonId);
+  add_esim_button_ = add_esim_button.get();
+  container()->AddView(TriView::Container::END, add_esim_button.release());
+};
+
+void NetworkListMobileHeaderView::OnToggleToggled(bool is_on) {
+  delegate()->OnMobileToggleClicked(is_on);
+}
+
+void NetworkListMobileHeaderView::AddESimButtonPressed() {
+  Shell::Get()->system_tray_model()->client()->ShowNetworkCreate(
+      ::onc::network_type::kCellular);
+}
+
+void NetworkListMobileHeaderView::SetAddESimButtonState(bool enabled,
+                                                        bool visible) {
+  if (!add_esim_button_)
+    return;
+
+  add_esim_button_->SetVisible(visible);
+  add_esim_button_->SetEnabled(enabled);
+  add_esim_button_->SetTooltipText(
+      l10n_util::GetStringUTF16(GetAddESimTooltipMessageId()));
+}
+
 }  // namespace ash
\ No newline at end of file
diff --git a/ash/system/network/network_list_mobile_header_view.h b/ash/system/network/network_list_mobile_header_view.h
index d782704d..8142805 100644
--- a/ash/system/network/network_list_mobile_header_view.h
+++ b/ash/system/network/network_list_mobile_header_view.h
@@ -6,11 +6,15 @@
 #define ASH_SYSTEM_NETWORK_NETWORK_LIST_MOBILE_HEADER_VIEW_H_
 
 #include "ash/ash_export.h"
+#include "ash/style/icon_button.h"
 #include "ash/system/network/network_list_network_header_view.h"
+#include "ash/system/tray/tri_view.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/views/view.h"
 
 namespace ash {
 
-// This class is the interface used to create network list header for Mobile
+// This class is the implementation of the network list header for Mobile
 // networks, and is responsible for the creation of mobile-specific buttons.
 class ASH_EXPORT NetworkListMobileHeaderView
     : public NetworkListNetworkHeaderView {
@@ -22,7 +26,25 @@
       delete;
   ~NetworkListMobileHeaderView() override;
 
-  virtual void SetAddESimButtonState(bool enabled, bool visible) = 0;
+ private:
+  friend class NetworkListMobileHeaderViewTest;
+
+  // Used for testing.
+  static constexpr int kAddESimButtonId =
+      NetworkListNetworkHeaderView::kToggleButtonId + 1;
+
+  // NetworkListNetworkHeaderView:
+  void AddExtraButtons() override;
+  void OnToggleToggled(bool is_on) override;
+
+  void AddESimButtonPressed();
+  void SetAddESimButtonState(bool enabled, bool visible);
+
+  // Button that navigates to the Settings mobile data subpage with the eSIM
+  // setup dialog open. This is null when the device is not eSIM-capable.
+  IconButton* add_esim_button_ = nullptr;
+
+  base::WeakPtrFactory<NetworkListMobileHeaderView> weak_factory_{this};
 };
 
 }  // namespace ash
diff --git a/ash/system/network/network_list_mobile_header_view_impl.cc b/ash/system/network/network_list_mobile_header_view_impl.cc
deleted file mode 100644
index 5e418be..0000000
--- a/ash/system/network/network_list_mobile_header_view_impl.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// 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 "ash/system/network/network_list_mobile_header_view_impl.h"
-
-#include "ash/ash_export.h"
-#include "ash/constants/ash_features.h"
-#include "ash/public/cpp/system_tray_client.h"
-#include "ash/resources/vector_icons/vector_icons.h"
-#include "ash/shell.h"
-#include "ash/strings/grit/ash_strings.h"
-#include "ash/style/icon_button.h"
-#include "ash/system/model/system_tray_model.h"
-#include "ash/system/network/network_list_mobile_header_view.h"
-#include "ash/system/network/network_list_network_header_view.h"
-#include "ash/system/network/tray_network_state_model.h"
-#include "ash/system/tray/tray_popup_utils.h"
-#include "ash/system/tray/tri_view.h"
-#include "base/memory/weak_ptr.h"
-#include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
-#include "components/onc/onc_constants.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/views/controls/image_view.h"
-#include "ui/views/view.h"
-
-namespace ash {
-namespace {
-
-using chromeos::network_config::mojom::DeviceStateProperties;
-using chromeos::network_config::mojom::DeviceStateType;
-using chromeos::network_config::mojom::NetworkType;
-
-int GetAddESimTooltipMessageId() {
-  const DeviceStateProperties* cellular_device =
-      Shell::Get()->system_tray_model()->network_state_model()->GetDevice(
-          NetworkType::kCellular);
-  if (!cellular_device)
-    return 0;
-
-  switch (cellular_device->inhibit_reason) {
-    case chromeos::network_config::mojom::InhibitReason::kInstallingProfile:
-      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_INSTALLING_PROFILE;
-    case chromeos::network_config::mojom::InhibitReason::kRenamingProfile:
-      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_RENAMING_PROFILE;
-    case chromeos::network_config::mojom::InhibitReason::kRemovingProfile:
-      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_REMOVING_PROFILE;
-    case chromeos::network_config::mojom::InhibitReason::kConnectingToProfile:
-      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_CONNECTING_TO_PROFILE;
-    case chromeos::network_config::mojom::InhibitReason::kRefreshingProfileList:
-      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_REFRESHING_PROFILE_LIST;
-    case chromeos::network_config::mojom::InhibitReason::kNotInhibited:
-      return IDS_ASH_STATUS_TRAY_ADD_CELLULAR_LABEL;
-    case chromeos::network_config::mojom::InhibitReason::kResettingEuiccMemory:
-      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_RESETTING_ESIM;
-    case chromeos::network_config::mojom::InhibitReason::kDisablingProfile:
-      return IDS_ASH_STATUS_TRAY_INHIBITED_CELLULAR_DISABLING_PROFILE;
-  }
-}
-
-}  // namespace
-
-NetworkListMobileHeaderViewImpl::NetworkListMobileHeaderViewImpl(
-    NetworkListNetworkHeaderView::Delegate* delegate)
-    : NetworkListMobileHeaderView(delegate) {
-  AddExtraButtons();
-}
-
-NetworkListMobileHeaderViewImpl::~NetworkListMobileHeaderViewImpl() = default;
-
-void NetworkListMobileHeaderViewImpl::AddExtraButtons() {
-  // The button navigates to Settings, only add it if this can occur.
-  if (!TrayPopupUtils::CanOpenWebUISettings())
-    return;
-
-  const gfx::VectorIcon& icon = base::i18n::IsRTL() ? kAddCellularNetworkRtlIcon
-                                                    : kAddCellularNetworkIcon;
-  std::unique_ptr<IconButton> add_esim_button = std::make_unique<IconButton>(
-      base::BindRepeating(
-          &NetworkListMobileHeaderViewImpl::AddESimButtonPressed,
-          weak_factory_.GetWeakPtr()),
-      IconButton::Type::kSmall, &icon, GetAddESimTooltipMessageId());
-  add_esim_button.get()->SetID(kAddESimButtonId);
-  add_esim_button_ = add_esim_button.get();
-  container()->AddView(TriView::Container::END, add_esim_button.release());
-};
-
-void NetworkListMobileHeaderViewImpl::OnToggleToggled(bool is_on) {
-  delegate()->OnMobileToggleClicked(is_on);
-}
-
-void NetworkListMobileHeaderViewImpl::AddESimButtonPressed() {
-  Shell::Get()->system_tray_model()->client()->ShowNetworkCreate(
-      ::onc::network_type::kCellular);
-}
-
-void NetworkListMobileHeaderViewImpl::SetAddESimButtonState(bool enabled,
-                                                            bool visible) {
-  if (!add_esim_button_)
-    return;
-
-  add_esim_button_->SetVisible(visible);
-  add_esim_button_->SetEnabled(enabled);
-  add_esim_button_->SetTooltipText(
-      l10n_util::GetStringUTF16(GetAddESimTooltipMessageId()));
-}
-
-}  // namespace ash
\ No newline at end of file
diff --git a/ash/system/network/network_list_mobile_header_view_impl.h b/ash/system/network/network_list_mobile_header_view_impl.h
deleted file mode 100644
index 5dfc90e..0000000
--- a/ash/system/network/network_list_mobile_header_view_impl.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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 ASH_SYSTEM_NETWORK_NETWORK_LIST_MOBILE_HEADER_VIEW_IMPL_H_
-#define ASH_SYSTEM_NETWORK_NETWORK_LIST_MOBILE_HEADER_VIEW_IMPL_H_
-
-#include "ash/ash_export.h"
-#include "ash/style/icon_button.h"
-#include "ash/system/network/network_list_mobile_header_view.h"
-#include "ash/system/network/network_list_network_header_view.h"
-#include "ash/system/tray/tri_view.h"
-#include "base/memory/weak_ptr.h"
-#include "ui/views/view.h"
-
-namespace ash {
-
-// Implementation of NetworkListMobileHeaderView.
-class ASH_EXPORT NetworkListMobileHeaderViewImpl
-    : public NetworkListMobileHeaderView {
- public:
-  explicit NetworkListMobileHeaderViewImpl(
-      NetworkListNetworkHeaderView::Delegate* delegate);
-  NetworkListMobileHeaderViewImpl(const NetworkListMobileHeaderViewImpl&) =
-      delete;
-  NetworkListMobileHeaderViewImpl& operator=(
-      const NetworkListMobileHeaderViewImpl&) = delete;
-  ~NetworkListMobileHeaderViewImpl() override;
-
- private:
-  friend class NetworkListMobileHeaderViewTest;
-
-  // Used for testing.
-  static constexpr int kAddESimButtonId =
-      NetworkListNetworkHeaderView::kToggleButtonId + 1;
-
-  // NetworkListNetworkHeaderView:
-  void AddExtraButtons() override;
-  void OnToggleToggled(bool is_on) override;
-
-  // NetworkListMobileHeaderView:
-  void SetAddESimButtonState(bool enabled, bool visible) override;
-
-  void AddESimButtonPressed();
-
-  // Button that navigates to the Settings mobile data subpage with the eSIM
-  // setup dialog open. This is null when the device is not eSIM-capable.
-  IconButton* add_esim_button_ = nullptr;
-
-  base::WeakPtrFactory<NetworkListMobileHeaderViewImpl> weak_factory_{this};
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_NETWORK_NETWORK_LIST_MOBILE_HEADER_VIEW_IMPL_H_
diff --git a/ash/system/network/network_list_mobile_header_view_unittest.cc b/ash/system/network/network_list_mobile_header_view_unittest.cc
index 123a0332..b8b4337e 100644
--- a/ash/system/network/network_list_mobile_header_view_unittest.cc
+++ b/ash/system/network/network_list_mobile_header_view_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/system/network/network_list_mobile_header_view_impl.h"
+#include "ash/system/network/network_list_mobile_header_view.h"
 
 #include <memory>
 
@@ -69,9 +69,9 @@
   }
 
   void Init() {
-    std::unique_ptr<NetworkListMobileHeaderViewImpl>
+    std::unique_ptr<NetworkListMobileHeaderView>
         network_list_mobile_header_view =
-            std::make_unique<NetworkListMobileHeaderViewImpl>(
+            std::make_unique<NetworkListMobileHeaderView>(
                 &fake_network_list_network_header_delegate_);
 
     widget_ = CreateFramelessTestWidget();
@@ -106,7 +106,7 @@
 
   IconButton* GetAddEsimButton() {
     return FindViewById<IconButton*>(
-        NetworkListMobileHeaderViewImpl::kAddESimButtonId);
+        NetworkListMobileHeaderView::kAddESimButtonId);
   }
 
   TrayToggleButton* GetToggleButton() {
@@ -136,7 +136,7 @@
   base::test::ScopedFeatureList feature_list_;
   FakeNetworkListNetworkHeaderViewDelegate
       fake_network_list_network_header_delegate_;
-  NetworkListMobileHeaderViewImpl* network_list_mobile_header_view_;
+  NetworkListMobileHeaderView* network_list_mobile_header_view_;
 };
 
 TEST_F(NetworkListMobileHeaderViewTest, HeaderLabel) {
diff --git a/ash/system/network/network_list_network_item_view.cc b/ash/system/network/network_list_network_item_view.cc
deleted file mode 100644
index 02556d2..0000000
--- a/ash/system/network/network_list_network_item_view.cc
+++ /dev/null
@@ -1,518 +0,0 @@
-// 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 "ash/system/network/network_list_network_item_view.h"
-
-#include <string>
-
-#include "ash/constants/ash_features.h"
-#include "ash/resources/vector_icons/vector_icons.h"
-#include "ash/session/session_controller_impl.h"
-#include "ash/shell.h"
-#include "ash/strings/grit/ash_strings.h"
-#include "ash/style/ash_color_provider.h"
-#include "ash/system/model/system_tray_model.h"
-#include "ash/system/network/network_icon.h"
-#include "ash/system/network/network_icon_animation.h"
-#include "ash/system/network/tray_network_state_model.h"
-#include "ash/system/power/power_status.h"
-#include "ash/system/tray/hover_highlight_view.h"
-#include "ash/system/tray/tray_info_label.h"
-#include "ash/system/tray/tray_popup_utils.h"
-#include "ash/system/tray/tray_utils.h"
-#include "base/i18n/number_formatting.h"
-#include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
-#include "network_list_network_item_view.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/metadata/metadata_impl_macros.h"
-#include "ui/gfx/image/image_skia.h"
-#include "ui/gfx/image/image_skia_operations.h"
-#include "ui/gfx/paint_vector_icon.h"
-#include "ui/views/accessibility/view_accessibility.h"
-#include "ui/views/controls/image_view.h"
-
-namespace ash {
-namespace {
-
-using chromeos::network_config::IsInhibited;
-using chromeos::network_config::NetworkTypeMatchesType;
-using chromeos::network_config::StateIsConnected;
-
-using chromeos::network_config::mojom::ActivationStateType;
-using chromeos::network_config::mojom::ConnectionStateType;
-using chromeos::network_config::mojom::NetworkStateProperties;
-using chromeos::network_config::mojom::NetworkStatePropertiesPtr;
-using chromeos::network_config::mojom::NetworkType;
-using chromeos::network_config::mojom::OncSource;
-using chromeos::network_config::mojom::ProxyMode;
-using chromeos::network_config::mojom::SecurityType;
-
-const int kMobileNetworkBatteryIconSize = 20;
-const int kPowerStatusPaddingRight = 10;
-const double kAlphaValueForInhibitedIconOpacity = 0.3;
-
-bool IsSecondaryUser() {
-  SessionControllerImpl* session_controller =
-      Shell::Get()->session_controller();
-  return session_controller->IsActiveUserSessionStarted() &&
-         !session_controller->IsUserPrimary();
-}
-
-bool NetworkTypeIsConfigurable(NetworkType type) {
-  switch (type) {
-    case NetworkType::kVPN:
-    case NetworkType::kWiFi:
-      return true;
-    case NetworkType::kAll:
-    case NetworkType::kCellular:
-    case NetworkType::kEthernet:
-    case NetworkType::kMobile:
-    case NetworkType::kTether:
-    case NetworkType::kWireless:
-      return false;
-  }
-  NOTREACHED();
-  return false;
-}
-
-ActivationStateType GetNetworkActivationState(
-    const NetworkStatePropertiesPtr& network_properties) {
-  if (NetworkTypeMatchesType(network_properties->type,
-                             NetworkType::kCellular)) {
-    return network_properties->type_state->get_cellular()->activation_state;
-  }
-
-  return ActivationStateType::kUnknown;
-}
-
-bool IsNetworkInhibited(const NetworkStatePropertiesPtr& network_properties) {
-  if (!NetworkTypeMatchesType(network_properties->type,
-                              NetworkType::kCellular)) {
-    return false;
-  }
-
-  const chromeos::network_config::mojom::DeviceStateProperties*
-      cellular_device =
-          Shell::Get()->system_tray_model()->network_state_model()->GetDevice(
-              NetworkType::kCellular);
-
-  return cellular_device && IsInhibited(cellular_device);
-}
-
-bool IsNetworkSimLocked(const NetworkStatePropertiesPtr& network_properties) {
-  return NetworkTypeMatchesType(network_properties->type,
-                                NetworkType::kCellular) &&
-         network_properties->type_state->get_cellular()->sim_locked;
-}
-
-bool IsNetworkConnectable(const NetworkStatePropertiesPtr& network_properties) {
-  // Network can be connected to if the network is not connected and:
-  // * The network is connectable or
-  // * The active user is primary and the network is configurable or
-  // * The network is cellular and activated
-  if (network_properties->connection_state !=
-      ConnectionStateType::kNotConnected) {
-    return false;
-  }
-
-  // Network cannot be connected to if it is an unactivated eSIM network.
-  if (network_properties->type == NetworkType::kCellular) {
-    if (GetNetworkActivationState(network_properties) ==
-            ActivationStateType::kNotActivated &&
-        !network_properties->type_state->get_cellular()->eid.empty()) {
-      return false;
-    }
-
-    if (GetNetworkActivationState(network_properties) ==
-        ActivationStateType::kActivated) {
-      return true;
-    }
-  }
-
-  if (network_properties->connectable &&
-      !IsNetworkInhibited(network_properties) &&
-      !IsNetworkSimLocked(network_properties)) {
-    return true;
-  }
-
-  if (!IsSecondaryUser() &&
-      NetworkTypeIsConfigurable(network_properties->type)) {
-    return true;
-  }
-
-  return false;
-}
-
-bool IsNetworkDisabled(const NetworkStatePropertiesPtr& network_properties) {
-  // If user is not logged in and SIM is locked disable the row.
-  if (!Shell::Get()->session_controller()->IsActiveUserSessionStarted() &&
-      IsNetworkSimLocked(network_properties)) {
-    return network_properties->type_state->get_cellular()->sim_locked;
-  }
-
-  // If the device is inhibited or network is blocked by policy, the network
-  // row should be disabled.
-  return GetNetworkActivationState(network_properties) ==
-             ActivationStateType::kActivating ||
-         network_properties->prohibited_by_policy ||
-         IsNetworkInhibited(network_properties);
-}
-
-bool IsNetworkSecured(const NetworkStatePropertiesPtr& network_properties) {
-  return NetworkTypeMatchesType(network_properties->type, NetworkType::kWiFi) &&
-         network_properties->type_state->get_wifi()->security !=
-             SecurityType::kNone;
-}
-
-bool IsNetworkManagedByPolicy(
-    const NetworkStatePropertiesPtr& network_properties) {
-  return network_properties->source == OncSource::kDevicePolicy ||
-         network_properties->source == OncSource::kUserPolicy;
-}
-
-bool ShouldShowActivateCellularNetwork(
-    const NetworkStatePropertiesPtr& network_properties) {
-  return GetNetworkActivationState(network_properties) ==
-             ActivationStateType::kNotActivated &&
-         network_properties->type_state->get_cellular()->eid.empty();
-}
-
-bool ShouldShowContactCarrier(
-    const NetworkStatePropertiesPtr& network_properties) {
-  return GetNetworkActivationState(network_properties) ==
-             ActivationStateType::kNotActivated &&
-         !network_properties->type_state->get_cellular()->eid.empty();
-}
-
-gfx::ImageSkia GetNetworkImageForNetwork(
-    const NetworkStatePropertiesPtr& network_properties) {
-  gfx::ImageSkia network_image;
-
-  const gfx::ImageSkia image = network_icon::GetImageForNonVirtualNetwork(
-      network_properties.get(), network_icon::ICON_TYPE_LIST,
-      /*badge_vpn=*/false);
-
-  if (NetworkTypeMatchesType(network_properties->type, NetworkType::kMobile) &&
-      network_properties->connection_state ==
-          ConnectionStateType::kNotConnected) {
-    // Mobile icons which are not connecting or connected should display a small
-    // "X" icon superimposed so that it is clear that they are disconnected.
-    const SkColor icon_color = AshColorProvider::Get()->GetContentLayerColor(
-        AshColorProvider::ContentLayerType::kIconColorPrimary);
-    network_image = gfx::ImageSkiaOperations::CreateSuperimposedImage(
-        image, gfx::CreateVectorIcon(kNetworkMobileNotConnectedXIcon,
-                                     image.height(), icon_color));
-  } else {
-    network_image = image;
-  }
-
-  // When the network is disabled, its appearance should be grayed out to
-  // indicate users that these networks are unavailable. We must change the
-  // image before we add it to the view, and then alter the label and sub-label
-  // if they exist after it is added to the view.
-  if (IsNetworkDisabled(network_properties)) {
-    network_image = gfx::ImageSkiaOperations::CreateTransparentImage(
-        network_image, kAlphaValueForInhibitedIconOpacity);
-  }
-  return network_image;
-}
-
-int GetCellularNetworkSubText(
-    const NetworkStatePropertiesPtr& network_properties) {
-  if (ShouldShowActivateCellularNetwork(network_properties))
-    return IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CLICK_TO_ACTIVATE;
-  if (ShouldShowContactCarrier(network_properties))
-    return IDS_ASH_STATUS_TRAY_NETWORK_UNAVAILABLE_SIM_NETWORK;
-  if (!IsNetworkSimLocked(network_properties))
-    return 0;
-  if (Shell::Get()->session_controller()->IsActiveUserSessionStarted())
-    return IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CLICK_TO_UNLOCK;
-  return IDS_ASH_STATUS_TRAY_NETWORK_STATUS_SIGN_IN_TO_UNLOCK;
-}
-
-}  // namespace
-
-NetworkListNetworkItemView::NetworkListNetworkItemView(
-    ViewClickListener* listener)
-    : NetworkListItemView(listener) {}
-
-NetworkListNetworkItemView::~NetworkListNetworkItemView() = default;
-
-void NetworkListNetworkItemView::UpdateViewForNetwork(
-    const NetworkStatePropertiesPtr& network_properties) {
-  network_properties_ = mojo::Clone(network_properties);
-
-  Reset();
-
-  const std::u16string label = GetLabel();
-  AddIconAndLabel(GetNetworkImageForNetwork(network_properties_), label);
-
-  if (network_properties_.get()->type == NetworkType::kCellular) {
-    SetupCellularSubtext();
-  } else {
-    SetupNetworkSubtext();
-  }
-
-  if (IsNetworkDisabled(network_properties)) {
-    UpdateDisabledTextColor();
-  }
-
-  if (network_properties_->prohibited_by_policy) {
-    SetTooltipText(
-        l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_PROHIBITED));
-  }
-
-  // Add an additional icon to the right of the label for networks
-  // that require it (e.g. Tether, controlled by extension).
-  if (network_properties_->type == NetworkType::kTether) {
-    AddPowerStatusView();
-  } else if (IsNetworkManagedByPolicy(network_properties)) {
-    AddPolicyView();
-  }
-
-  SetAccessibleName(GenerateAccessibilityLabel(label));
-  GetViewAccessibility().OverrideDescription(
-      GenerateAccessibilityDescription());
-}
-
-void NetworkListNetworkItemView::SetupCellularSubtext() {
-  int cellular_subtext_message_id =
-      GetCellularNetworkSubText(network_properties_);
-
-  if (!cellular_subtext_message_id) {
-    SetupNetworkSubtext();
-    return;
-  }
-
-  if (text_label()) {
-    const SkColor primary_text_color =
-        AshColorProvider::Get()->GetContentLayerColor(
-            AshColorProvider::ContentLayerType::kTextColorPrimary);
-    text_label()->SetEnabledColor(primary_text_color);
-  }
-
-  SetSubText(l10n_util::GetStringUTF16(cellular_subtext_message_id));
-  const SkColor sub_text_color = AshColorProvider::Get()->GetContentLayerColor(
-      AshColorProvider::ContentLayerType::kTextColorWarning);
-  sub_text_label()->SetEnabledColor(sub_text_color);
-}
-
-void NetworkListNetworkItemView::SetupNetworkSubtext() {
-  if (StateIsConnected(network_properties()->connection_state)) {
-    SetupConnectedScrollListItem(this);
-  } else if (network_properties_.get()->connection_state ==
-             ConnectionStateType::kConnecting) {
-    SetupConnectingScrollListItem(this);
-  }
-}
-
-void NetworkListNetworkItemView::UpdateDisabledTextColor() {
-  if (text_label()) {
-    SkColor primary_text_color = text_label()->GetEnabledColor();
-    text_label()->SetEnabledColor(
-        AshColorProvider::GetDisabledColor(primary_text_color));
-  }
-  if (sub_text_label()) {
-    SkColor sub_text_color = sub_text_label()->GetEnabledColor();
-    sub_text_label()->SetEnabledColor(
-        AshColorProvider::GetDisabledColor(sub_text_color));
-  }
-}
-
-void NetworkListNetworkItemView::AddPowerStatusView() {
-  auto image_icon = std::make_unique<views::ImageView>();
-  const SkColor icon_color = AshColorProvider::Get()->GetContentLayerColor(
-      AshColorProvider::ContentLayerType::kIconColorPrimary);
-  image_icon->SetPreferredSize(gfx::Size(kMenuIconSize, kMenuIconSize));
-  image_icon->SetFlipCanvasOnPaintForRTLUI(true);
-  PowerStatus::BatteryImageInfo icon_info;
-
-  int battery_percentage =
-      network_properties()->type_state->get_tether()->battery_percentage;
-  icon_info.charge_percent = battery_percentage;
-  image_icon->SetImage(PowerStatus::GetBatteryImage(
-      icon_info, kMobileNetworkBatteryIconSize,
-      AshColorProvider::GetSecondToneColor(icon_color), icon_color));
-
-  // Show the numeric battery percentage on hover.
-  image_icon->SetTooltipText(base::FormatPercent(battery_percentage));
-
-  AddRightView(image_icon.release(), views::CreateEmptyBorder(gfx::Insets::TLBR(
-                                         0, 0, 0, kPowerStatusPaddingRight)));
-}
-
-void NetworkListNetworkItemView::AddPolicyView() {
-  std::unique_ptr<views::ImageView> controlled_icon(
-      TrayPopupUtils::CreateMainImageView());
-  const SkColor icon_color = AshColorProvider::Get()->GetContentLayerColor(
-      AshColorProvider::ContentLayerType::kIconColorPrimary);
-  controlled_icon->SetImage(
-      gfx::CreateVectorIcon(kSystemMenuBusinessIcon, icon_color));
-  AddRightView(controlled_icon.release());
-}
-
-std::u16string NetworkListNetworkItemView::GenerateAccessibilityLabel(
-    std::u16string label) {
-  if (IsNetworkConnectable(network_properties())) {
-    return l10n_util::GetStringFUTF16(
-        IDS_ASH_STATUS_TRAY_NETWORK_A11Y_LABEL_CONNECT, label);
-  }
-
-  if (ShouldShowActivateCellularNetwork(network_properties())) {
-    return l10n_util::GetStringFUTF16(
-        IDS_ASH_STATUS_TRAY_NETWORK_A11Y_LABEL_ACTIVATE, label);
-  }
-
-  if (ShouldShowContactCarrier(network_properties())) {
-    return l10n_util::GetStringFUTF16(
-        IDS_ASH_STATUS_TRAY_NETWORK_A11Y_UNAVAILABLE_SIM_NETWORK, label);
-  }
-
-  return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_A11Y_LABEL_OPEN,
-                                    label);
-}
-
-std::u16string
-NetworkListNetworkItemView::GenerateAccessibilityDescriptionForEthernet(
-    const std::u16string connection_status) {
-  if (!connection_status.empty()) {
-    if (IsNetworkManagedByPolicy(network_properties())) {
-      return l10n_util::GetStringFUTF16(
-          IDS_ASH_STATUS_TRAY_ETHERNET_A11Y_DESC_MANAGED_WITH_CONNECTION_STATUS,
-          connection_status);
-    }
-    return connection_status;
-  }
-  if (IsNetworkManagedByPolicy(network_properties())) {
-    return l10n_util::GetStringUTF16(
-        IDS_ASH_STATUS_TRAY_ETHERNET_A11Y_DESC_MANAGED);
-  }
-  return GetLabel();
-}
-
-std::u16string
-NetworkListNetworkItemView::GenerateAccessibilityDescriptionForWifi(
-    const std::u16string connection_status,
-    int signal_strength) {
-  std::u16string security_label = l10n_util::GetStringUTF16(
-      IsNetworkSecured(network_properties())
-          ? IDS_ASH_STATUS_TRAY_NETWORK_STATUS_SECURED
-          : IDS_ASH_STATUS_TRAY_NETWORK_STATUS_UNSECURED);
-  if (!connection_status.empty()) {
-    if (IsNetworkManagedByPolicy(network_properties())) {
-      return l10n_util::GetStringFUTF16(
-          IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC_MANAGED_WITH_CONNECTION_STATUS,
-          security_label, connection_status,
-          base::FormatPercent(signal_strength));
-    }
-    return l10n_util::GetStringFUTF16(
-        IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC_WITH_CONNECTION_STATUS,
-        security_label, connection_status,
-        base::FormatPercent(signal_strength));
-  }
-  if (IsNetworkManagedByPolicy(network_properties())) {
-    return l10n_util::GetStringFUTF16(
-        IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC_MANAGED, security_label,
-        base::FormatPercent(signal_strength));
-  }
-  return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_WIFI_NETWORK_A11Y_DESC,
-                                    security_label,
-                                    base::FormatPercent(signal_strength));
-}
-
-std::u16string
-NetworkListNetworkItemView::GenerateAccessibilityDescriptionForCellular(
-    const std::u16string connection_status,
-    int signal_strength) {
-  if (ShouldShowActivateCellularNetwork(network_properties())) {
-    return l10n_util::GetStringUTF16(
-        IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CLICK_TO_ACTIVATE);
-  }
-  if (ShouldShowContactCarrier(network_properties())) {
-    return l10n_util::GetStringUTF16(
-        IDS_ASH_STATUS_TRAY_NETWORK_UNAVAILABLE_SIM_NETWORK);
-  }
-  if (IsNetworkSimLocked(network_properties())) {
-    if (Shell::Get()->session_controller()->IsActiveUserSessionStarted()) {
-      return l10n_util::GetStringUTF16(
-          IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CLICK_TO_UNLOCK);
-    }
-    return l10n_util::GetStringUTF16(
-        IDS_ASH_STATUS_TRAY_NETWORK_STATUS_SIGN_IN_TO_UNLOCK);
-  }
-  if (!connection_status.empty()) {
-    if (IsNetworkManagedByPolicy(network_properties())) {
-      return l10n_util::GetStringFUTF16(
-          IDS_ASH_STATUS_TRAY_CELLULAR_NETWORK_A11Y_DESC_MANAGED_WITH_CONNECTION_STATUS,
-          connection_status, base::FormatPercent(signal_strength));
-    }
-    return l10n_util::GetStringFUTF16(
-        IDS_ASH_STATUS_TRAY_CELLULAR_NETWORK_A11Y_DESC_WITH_CONNECTION_STATUS,
-        connection_status, base::FormatPercent(signal_strength));
-  }
-  if (IsNetworkManagedByPolicy(network_properties())) {
-    return l10n_util::GetStringFUTF16(
-        IDS_ASH_STATUS_TRAY_CELLULAR_NETWORK_A11Y_DESC_MANAGED,
-        base::FormatPercent(signal_strength));
-  }
-  return l10n_util::GetStringFUTF16(
-      IDS_ASH_STATUS_TRAY_CELLULAR_NETWORK_A11Y_DESC,
-      base::FormatPercent(signal_strength));
-}
-
-std::u16string
-NetworkListNetworkItemView::GenerateAccessibilityDescriptionForTether(
-    const std::u16string connection_status,
-    int signal_strength) {
-  int battery_percentage =
-      network_properties()->type_state->get_tether()->battery_percentage;
-  if (!connection_status.empty()) {
-    return l10n_util::GetStringFUTF16(
-        IDS_ASH_STATUS_TRAY_TETHER_NETWORK_A11Y_DESC_WITH_CONNECTION_STATUS,
-        connection_status, base::FormatPercent(signal_strength),
-        base::FormatPercent(battery_percentage));
-  }
-  return l10n_util::GetStringFUTF16(
-      IDS_ASH_STATUS_TRAY_TETHER_NETWORK_A11Y_DESC,
-      base::FormatPercent(signal_strength),
-      base::FormatPercent(battery_percentage));
-}
-
-std::u16string NetworkListNetworkItemView::GenerateAccessibilityDescription() {
-  std::u16string connection_status;
-  if (StateIsConnected(network_properties()->connection_state) ||
-      network_properties()->connection_state ==
-          ConnectionStateType::kConnecting) {
-    connection_status = l10n_util::GetStringUTF16(
-        StateIsConnected(network_properties()->connection_state)
-            ? IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED
-            : IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTING);
-  }
-
-  int signal_strength = chromeos::network_config::GetWirelessSignalStrength(
-      network_properties().get());
-
-  switch (network_properties()->type) {
-    case NetworkType::kEthernet:
-      return GenerateAccessibilityDescriptionForEthernet(connection_status);
-    case NetworkType::kWiFi:
-      return GenerateAccessibilityDescriptionForWifi(connection_status,
-                                                     signal_strength);
-    case NetworkType::kCellular:
-      return GenerateAccessibilityDescriptionForCellular(connection_status,
-                                                         signal_strength);
-    case NetworkType::kTether: {
-      return GenerateAccessibilityDescriptionForTether(connection_status,
-                                                       signal_strength);
-    }
-    default:
-      return u"";
-  }
-}
-
-BEGIN_METADATA(NetworkListNetworkItemView, NetworkListItemView)
-END_METADATA
-
-}  // namespace ash
\ No newline at end of file
diff --git a/ash/system/network/network_list_network_item_view.h b/ash/system/network/network_list_network_item_view.h
deleted file mode 100644
index 34bfb40..0000000
--- a/ash/system/network/network_list_network_item_view.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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 ASH_SYSTEM_NETWORK_NETWORK_LIST_NETWORK_ITEM_VIEW_H_
-#define ASH_SYSTEM_NETWORK_NETWORK_LIST_NETWORK_ITEM_VIEW_H_
-
-#include "ash/ash_export.h"
-#include "ash/system/network/network_info.h"
-#include "ash/system/network/network_list_item_view.h"
-#include "ash/system/tray/hover_highlight_view.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
-#include "ui/base/metadata/metadata_impl_macros.h"
-#include "ui/views/view.h"
-
-namespace ash {
-
-class ViewClickListener;
-
-// This class encapsulates the logic of configuring the view shown for a single
-// network (Mobile and Wifi) in the detailed Network page within the quick
-// settings.
-class ASH_EXPORT NetworkListNetworkItemView : public NetworkListItemView {
- public:
-  METADATA_HEADER(NetworkListNetworkItemView);
-
-  explicit NetworkListNetworkItemView(ViewClickListener* listener);
-  NetworkListNetworkItemView(const NetworkListNetworkItemView&) = delete;
-  NetworkListNetworkItemView& operator=(const NetworkListNetworkItemView&) =
-      delete;
-  ~NetworkListNetworkItemView() override;
-
- private:
-  friend class NetworkListNetworkItemViewTest;
-
-  // NetworkListItemView:
-  void UpdateViewForNetwork(
-      const chromeos::network_config::mojom::NetworkStatePropertiesPtr&
-          network_properties) override;
-
-  void SetupCellularSubtext();
-  void SetupNetworkSubtext();
-  void UpdateDisabledTextColor();
-  void AddPowerStatusView();
-  void AddPolicyView();
-  std::u16string GenerateAccessibilityDescriptionForEthernet(
-      const std::u16string connection_status);
-  std::u16string GenerateAccessibilityDescriptionForWifi(
-      const std::u16string connection_status,
-      int signal_strength);
-  std::u16string GenerateAccessibilityDescriptionForCellular(
-      const std::u16string connection_status,
-      int signal_strength);
-  std::u16string GenerateAccessibilityDescriptionForTether(
-      const std::u16string connection_status,
-      int signal_strength);
-  std::u16string GenerateAccessibilityLabel(const std::u16string label);
-  std::u16string GenerateAccessibilityDescription();
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_NETWORK_NETWORK_LIST_NETWORK_ITEM_VIEW_H_
\ No newline at end of file
diff --git a/ash/system/network/network_list_network_item_view_unittest.cc b/ash/system/network/network_list_network_item_view_unittest.cc
deleted file mode 100644
index bdfa941..0000000
--- a/ash/system/network/network_list_network_item_view_unittest.cc
+++ /dev/null
@@ -1,407 +0,0 @@
-// 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 "ash/system/network/network_list_network_item_view.h"
-
-#include <memory>
-
-#include "ash/constants/ash_features.h"
-#include "ash/resources/vector_icons/vector_icons.h"
-#include "ash/shell.h"
-#include "ash/strings/grit/ash_strings.h"
-#include "ash/style/ash_color_provider.h"
-#include "ash/system/network/fake_network_detailed_network_view.h"
-#include "ash/system/network/network_icon.h"
-#include "ash/system/network/network_info.h"
-#include "ash/test/ash_test_base.h"
-#include "base/i18n/number_formatting.h"
-#include "base/test/scoped_feature_list.h"
-#include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
-#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/image/image_unittest_util.h"
-#include "ui/gfx/paint_vector_icon.h"
-#include "ui/gfx/vector_icon_types.h"
-#include "ui/views/accessibility/view_accessibility.h"
-#include "ui/views/controls/image_view.h"
-#include "ui/views/view.h"
-#include "ui/views/view_utils.h"
-
-namespace ash {
-
-namespace {
-
-using chromeos::network_config::CrosNetworkConfigTestHelper;
-
-using chromeos::network_config::mojom::ActivationStateType;
-using chromeos::network_config::mojom::ConnectionStateType;
-using chromeos::network_config::mojom::NetworkStatePropertiesPtr;
-using chromeos::network_config::mojom::NetworkType;
-using chromeos::network_config::mojom::OncSource;
-using chromeos::network_config::mojom::SecurityType;
-
-const std::string kWiFiName = "Silent WiFi";
-const std::string kCellularName = "Strong WiFi";
-const std::string kTetherName = "tether";
-const std::string kEid = "sim_eid";
-const std::string kEthernet = "ethernet";
-
-const char kStubEthernetDeviceName[] = "stub_ethernet_device";
-const char kStubEthernetDevicePath[] = "/device/stub_ethernet_device";
-const char kStubWiFiDeviceName[] = "stub_wifi_device";
-const char kStubWiFiDevicePath[] = "/device/stub_wifi_device";
-const char kStubCellularDeviceName[] = "stub_cellular_device";
-const char kStubCellularDevicePath[] = "/device/stub_cellular_device";
-
-}  // namespace
-
-class NetworkListNetworkItemViewTest : public AshTestBase {
- public:
-  void SetUp() override {
-    AshTestBase::SetUp();
-
-    feature_list_.InitAndEnableFeature(features::kQuickSettingsNetworkRevamp);
-
-    SetUpDefaultNetworkDevices();
-
-    fake_network_detailed_network_view_ =
-        std::make_unique<FakeNetworkDetailedNetworkView>(
-            /*delegate=*/nullptr);
-
-    std::unique_ptr<NetworkListNetworkItemView> network_list_network_item_view =
-        std::make_unique<NetworkListNetworkItemView>(
-            fake_network_detailed_network_view_.get());
-
-    widget_ = CreateFramelessTestWidget();
-    widget_->SetFullscreen(true);
-
-    NetworkStatePropertiesPtr wifi_network = CreateStandaloneNetworkProperties(
-        kWiFiName, NetworkType::kWiFi, ConnectionStateType::kNotConnected, 50);
-
-    network_list_network_item_view_ =
-        widget_->SetContentsView(std::move(network_list_network_item_view));
-    network_list_network_item_view_->UpdateViewForNetwork(wifi_network);
-  }
-
-  void TearDown() override {
-    widget_.reset();
-
-    AshTestBase::TearDown();
-  }
-
-  NetworkListNetworkItemView* network_list_network_item_view() {
-    return network_list_network_item_view_;
-  }
-
-  const NetworkListItemView* last_clicked_network_list_item() {
-    return fake_network_detailed_network_view_
-        ->last_clicked_network_list_item();
-  }
-
-  NetworkStatePropertiesPtr CreateStandaloneNetworkProperties(
-      const std::string& id,
-      NetworkType type,
-      ConnectionStateType connection_state,
-      int signal_strength) {
-    return network_config_helper_.CreateStandaloneNetworkProperties(
-        id, type, connection_state, signal_strength);
-  }
-
-  void UpdateViewForNetwork(NetworkStatePropertiesPtr& network) {
-    network_list_network_item_view()->UpdateViewForNetwork(network);
-  }
-
-  void AssertA11yDescription(NetworkStatePropertiesPtr& network_properties) {
-    ui::AXNodeData node_data;
-    UpdateViewForNetwork(network_properties);
-    network_list_network_item_view()
-        ->GetViewAccessibility()
-        .GetAccessibleNodeData(&node_data);
-    std::u16string description =
-        network_list_network_item_view()->GenerateAccessibilityDescription();
-    std::string a11ydescription =
-        node_data.GetStringAttribute(ax::mojom::StringAttribute::kDescription);
-    EXPECT_EQ(base::UTF8ToUTF16(a11ydescription), description);
-  }
-
- private:
-  void SetUpDefaultNetworkDevices() {
-    network_state_helper()->ClearDevices();
-    network_state_helper()->AddDevice(
-        kStubCellularDevicePath, shill::kTypeCellular, kStubCellularDeviceName);
-    network_state_helper()->AddDevice(
-        kStubEthernetDevicePath, shill::kTypeEthernet, kStubEthernetDeviceName);
-    network_state_helper()->AddDevice(kStubWiFiDevicePath, shill::kTypeWifi,
-                                      kStubWiFiDeviceName);
-  }
-
-  chromeos::NetworkStateTestHelper* network_state_helper() {
-    return &network_config_helper_.network_state_helper();
-  }
-
-  base::test::ScopedFeatureList feature_list_;
-  std::unique_ptr<views::Widget> widget_;
-  std::unique_ptr<FakeNetworkDetailedNetworkView>
-      fake_network_detailed_network_view_;
-  CrosNetworkConfigTestHelper network_config_helper_;
-  NetworkListNetworkItemView* network_list_network_item_view_;
-};
-
-TEST_F(NetworkListNetworkItemViewTest, HasCorrectLabel) {
-  ASSERT_TRUE(network_list_network_item_view()->text_label());
-
-  EXPECT_EQ(base::UTF8ToUTF16(kWiFiName),
-            network_list_network_item_view()->text_label()->GetText());
-
-  const std::string kNewWifiName = "New wifi";
-
-  NetworkStatePropertiesPtr wifi_network = CreateStandaloneNetworkProperties(
-      kWiFiName, NetworkType::kWiFi, ConnectionStateType::kNotConnected, 50);
-  wifi_network->name = kNewWifiName;
-  UpdateViewForNetwork(wifi_network);
-
-  EXPECT_EQ(base::UTF8ToUTF16(kNewWifiName),
-            network_list_network_item_view()->text_label()->GetText());
-}
-
-TEST_F(NetworkListNetworkItemViewTest, HasCorrectSublabel) {
-  EXPECT_FALSE(network_list_network_item_view()->sub_text_label());
-
-  NetworkStatePropertiesPtr wifi_network = CreateStandaloneNetworkProperties(
-      kWiFiName, NetworkType::kWiFi, ConnectionStateType::kConnected, 50);
-
-  UpdateViewForNetwork(wifi_network);
-  EXPECT_TRUE(network_list_network_item_view()->sub_text_label());
-  EXPECT_EQ(
-      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED),
-      network_list_network_item_view()->sub_text_label()->GetText());
-
-  wifi_network->connection_state = ConnectionStateType::kConnecting;
-  UpdateViewForNetwork(wifi_network);
-  EXPECT_EQ(
-      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTING),
-      network_list_network_item_view()->sub_text_label()->GetText());
-
-  // Label for pSIM networks that are connected but not yet activated.
-  NetworkStatePropertiesPtr cellular_network =
-      CreateStandaloneNetworkProperties(kWiFiName, NetworkType::kCellular,
-                                        ConnectionStateType::kConnected, 50);
-  cellular_network->type_state->get_cellular()->activation_state =
-      ActivationStateType::kNotActivated;
-  UpdateViewForNetwork(cellular_network);
-  EXPECT_EQ(l10n_util::GetStringUTF16(
-                IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CLICK_TO_ACTIVATE),
-            network_list_network_item_view()->sub_text_label()->GetText());
-
-  // Label for unactivated eSIM networks.
-  cellular_network->type_state->get_cellular()->eid = kEid;
-  UpdateViewForNetwork(cellular_network);
-  EXPECT_EQ(l10n_util::GetStringUTF16(
-                IDS_ASH_STATUS_TRAY_NETWORK_UNAVAILABLE_SIM_NETWORK),
-            network_list_network_item_view()->sub_text_label()->GetText());
-
-  // label for connected unlocked cellular network.
-  cellular_network->type_state->get_cellular()->activation_state =
-      ActivationStateType::kActivated;
-  cellular_network->type_state->get_cellular()->sim_locked = false;
-  UpdateViewForNetwork(cellular_network);
-  EXPECT_EQ(
-      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CONNECTED),
-      network_list_network_item_view()->sub_text_label()->GetText());
-
-  cellular_network->connection_state = ConnectionStateType::kNotConnected;
-  UpdateViewForNetwork(cellular_network);
-  EXPECT_FALSE(network_list_network_item_view()->sub_text_label());
-
-  // label for locked cellular network.
-  cellular_network->type_state->get_cellular()->sim_locked = true;
-  cellular_network->connection_state = ConnectionStateType::kConnected;
-  UpdateViewForNetwork(cellular_network);
-  EXPECT_EQ(l10n_util::GetStringUTF16(
-                IDS_ASH_STATUS_TRAY_NETWORK_STATUS_CLICK_TO_UNLOCK),
-            network_list_network_item_view()->sub_text_label()->GetText());
-}
-
-TEST_F(NetworkListNetworkItemViewTest, NotifiesListenerWhenClicked) {
-  EXPECT_FALSE(last_clicked_network_list_item());
-  LeftClickOn(network_list_network_item_view());
-  EXPECT_EQ(last_clicked_network_list_item(), network_list_network_item_view());
-}
-
-TEST_F(NetworkListNetworkItemViewTest, HasEnterpriseIconWhenBlockedByPolicy) {
-  EXPECT_FALSE(network_list_network_item_view()->right_view());
-
-  NetworkStatePropertiesPtr wifi_network = CreateStandaloneNetworkProperties(
-      kWiFiName, NetworkType::kWiFi, ConnectionStateType::kConnected, 50);
-  wifi_network->source = OncSource::kDevicePolicy;
-  UpdateViewForNetwork(wifi_network);
-
-  ASSERT_TRUE(network_list_network_item_view()->right_view());
-  EXPECT_TRUE(network_list_network_item_view()->right_view()->GetVisible());
-  ASSERT_TRUE(views::IsViewClass<views::ImageView>(
-      network_list_network_item_view()->right_view()));
-
-  const gfx::Image expected_image(CreateVectorIcon(
-      kSystemMenuBusinessIcon,
-      AshColorProvider::Get()->GetContentLayerColor(
-          AshColorProvider::ContentLayerType::kIconColorPrimary)));
-  const gfx::Image actual_image(
-      static_cast<views::ImageView*>(
-          network_list_network_item_view()->right_view())
-          ->GetImage());
-
-  EXPECT_TRUE(gfx::test::AreImagesEqual(expected_image, actual_image));
-
-  wifi_network->source = OncSource::kNone;
-  UpdateViewForNetwork(wifi_network);
-  ASSERT_FALSE(network_list_network_item_view()->right_view());
-}
-
-TEST_F(NetworkListNetworkItemViewTest, HasPoweredIcon) {
-  EXPECT_FALSE(network_list_network_item_view()->right_view());
-  int battery_percentage = 50;
-
-  NetworkStatePropertiesPtr tether_network = CreateStandaloneNetworkProperties(
-      kTetherName, NetworkType::kTether, ConnectionStateType::kConnected,
-      battery_percentage);
-
-  tether_network->type_state->get_tether()->battery_percentage =
-      battery_percentage;
-  UpdateViewForNetwork(tether_network);
-
-  ASSERT_TRUE(network_list_network_item_view()->right_view());
-  EXPECT_TRUE(network_list_network_item_view()->right_view()->GetVisible());
-  ASSERT_TRUE(views::IsViewClass<views::ImageView>(
-      network_list_network_item_view()->right_view()));
-
-  EXPECT_EQ(base::FormatPercent(battery_percentage),
-            static_cast<views::ImageView*>(
-                network_list_network_item_view()->right_view())
-                ->GetTooltipText());
-}
-
-TEST_F(NetworkListNetworkItemViewTest, HasExpectedA11yText) {
-  NetworkStatePropertiesPtr wifi_network = CreateStandaloneNetworkProperties(
-      kWiFiName, NetworkType::kWiFi, ConnectionStateType::kConnected, 50);
-  wifi_network->connection_state = ConnectionStateType::kConnected;
-
-  UpdateViewForNetwork(wifi_network);
-  EXPECT_EQ(
-      l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_A11Y_LABEL_OPEN,
-                                 base::UTF8ToUTF16(kWiFiName)),
-      network_list_network_item_view()->GetAccessibleName());
-
-  // Network can be connected to.
-  wifi_network->connectable = true;
-  wifi_network->connection_state = ConnectionStateType::kNotConnected;
-  UpdateViewForNetwork(wifi_network);
-
-  EXPECT_EQ(
-      l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_NETWORK_A11Y_LABEL_CONNECT,
-                                 base::UTF8ToUTF16(kWiFiName)),
-      network_list_network_item_view()->GetAccessibleName());
-
-  // Activate cellular network A11Y label is shown when a pSIM network is
-  // connected but not yet activated.
-  NetworkStatePropertiesPtr cellular_network =
-      CreateStandaloneNetworkProperties(kCellularName, NetworkType::kCellular,
-                                        ConnectionStateType::kConnected, 50);
-  cellular_network->connectable = true;
-  cellular_network->connection_state = ConnectionStateType::kConnected;
-  cellular_network->type_state->get_cellular()->activation_state =
-      ActivationStateType::kNotActivated;
-  UpdateViewForNetwork(cellular_network);
-
-  EXPECT_EQ(l10n_util::GetStringFUTF16(
-                IDS_ASH_STATUS_TRAY_NETWORK_A11Y_LABEL_ACTIVATE,
-                base::UTF8ToUTF16(kCellularName)),
-            network_list_network_item_view()->GetAccessibleName());
-
-  // Contact carrier A11Y label is shown when a eSIM network is connected but
-  // not yet activated.
-  cellular_network->type_state->get_cellular()->eid = kEid;
-  UpdateViewForNetwork(cellular_network);
-  EXPECT_EQ(l10n_util::GetStringFUTF16(
-                IDS_ASH_STATUS_TRAY_NETWORK_A11Y_UNAVAILABLE_SIM_NETWORK,
-                base::UTF8ToUTF16(kCellularName)),
-            network_list_network_item_view()->GetAccessibleName());
-}
-
-TEST_F(NetworkListNetworkItemViewTest, HasExpectedDescription) {
-  ConnectionStateType connection_states[3] = {
-      ConnectionStateType::kConnected, ConnectionStateType::kConnecting,
-      ConnectionStateType::kNotConnected};
-  OncSource policies[2]{OncSource::kDevicePolicy, OncSource::kNone};
-
-  // A11Y description for Ethernet networks.
-  NetworkStatePropertiesPtr ethernet_network =
-      CreateStandaloneNetworkProperties(kEthernet, NetworkType::kEthernet,
-                                        ConnectionStateType::kConnected, 50);
-  for (const auto& connection : connection_states) {
-    ethernet_network->connection_state = connection;
-    AssertA11yDescription(ethernet_network);
-    for (const auto& policy : policies) {
-      ethernet_network->source = policy;
-      AssertA11yDescription(ethernet_network);
-    }
-  }
-
-  // A11Y description for WiFi networks.
-  SecurityType security_types[2] = {SecurityType::kNone, SecurityType::kWepPsk};
-
-  NetworkStatePropertiesPtr wifi_network = CreateStandaloneNetworkProperties(
-      kWiFiName, NetworkType::kWiFi, ConnectionStateType::kConnected, 50);
-
-  for (const auto& connection : connection_states) {
-    wifi_network->connection_state = connection;
-    AssertA11yDescription(wifi_network);
-    for (const auto& security : security_types) {
-      wifi_network->type_state->get_wifi()->security = security;
-      AssertA11yDescription(wifi_network);
-      for (const auto& policy : policies) {
-        wifi_network->source = policy;
-        AssertA11yDescription(wifi_network);
-      }
-    }
-  }
-
-  // A11Y description for Celular networks.
-  ActivationStateType activation_states[2]{ActivationStateType::kNotActivated,
-                                           ActivationStateType::kActivated};
-  bool locked[2]{true, false};
-
-  NetworkStatePropertiesPtr cellular_network =
-      CreateStandaloneNetworkProperties(kCellularName, NetworkType::kCellular,
-                                        ConnectionStateType::kConnected, 50);
-
-  for (const auto& connection : connection_states) {
-    cellular_network->connection_state = connection;
-    AssertA11yDescription(cellular_network);
-    for (const auto& activation_state : activation_states) {
-      cellular_network->type_state->get_cellular()->activation_state =
-          activation_state;
-      AssertA11yDescription(cellular_network);
-      for (const auto& lock : locked) {
-        cellular_network->type_state->get_cellular()->sim_locked = lock;
-        AssertA11yDescription(cellular_network);
-        for (const auto& policy : policies) {
-          cellular_network->source = policy;
-          AssertA11yDescription(cellular_network);
-        }
-      }
-    }
-  }
-
-  // A11Y description for Tether networks.
-  NetworkStatePropertiesPtr tether_network = CreateStandaloneNetworkProperties(
-      kTetherName, NetworkType::kTether, ConnectionStateType::kConnected, 50);
-  tether_network->type_state->get_tether()->battery_percentage = 20;
-  for (const auto& connection : connection_states) {
-    tether_network->connection_state = connection;
-    AssertA11yDescription(tether_network);
-  }
-}
-
-}  // namespace ash
diff --git a/ash/system/network/network_list_wifi_header_view.cc b/ash/system/network/network_list_wifi_header_view.cc
index da9f4a52..0dd2c14 100644
--- a/ash/system/network/network_list_wifi_header_view.cc
+++ b/ash/system/network/network_list_wifi_header_view.cc
@@ -4,16 +4,74 @@
 
 #include "ash/system/network/network_list_wifi_header_view.h"
 
+#include "ash/constants/ash_features.h"
+#include "ash/public/cpp/system_tray_client.h"
+#include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
+#include "ash/style/icon_button.h"
+#include "ash/system/model/system_tray_model.h"
 #include "ash/system/network/network_list_network_header_view.h"
+#include "ash/system/network/tray_network_state_model.h"
+#include "ash/system/tray/tri_view.h"
+#include "base/memory/weak_ptr.h"
+#include "base/metrics/user_metrics.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
+#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "components/onc/onc_constants.h"
+#include "components/vector_icons/vector_icons.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/view.h"
 
 namespace ash {
+namespace {
+using chromeos::network_config::mojom::DeviceStateType;
+using chromeos::network_config::mojom::NetworkType;
+}  // namespace
 
 NetworkListWifiHeaderView::NetworkListWifiHeaderView(
     NetworkListNetworkHeaderView::Delegate* delegate)
     : NetworkListNetworkHeaderView(delegate, IDS_ASH_STATUS_TRAY_NETWORK_WIFI) {
+  AddExtraButtons();
 }
 
 NetworkListWifiHeaderView::~NetworkListWifiHeaderView() = default;
 
+void NetworkListWifiHeaderView::AddExtraButtons() {
+  std::unique_ptr<IconButton> join_wifi_button = std::make_unique<IconButton>(
+      base::BindRepeating(&NetworkListWifiHeaderView::JoinWifiButtonPressed,
+                          weak_factory_.GetWeakPtr()),
+      IconButton::Type::kSmall, &vector_icons::kWifiAddIcon,
+      IDS_ASH_STATUS_TRAY_OTHER_WIFI);
+
+  join_wifi_button.get()->SetID(kJoinWifiButtonId);
+  join_wifi_button_ = join_wifi_button.get();
+  container()->AddView(TriView::Container::END, join_wifi_button.release());
+};
+
+void NetworkListWifiHeaderView::SetToggleState(bool enabled, bool is_on) {
+  join_wifi_button_->SetEnabled(enabled && is_on);
+  NetworkListNetworkHeaderView::SetToggleState(enabled, is_on);
+}
+
+void NetworkListWifiHeaderView::OnToggleToggled(bool is_on) {
+  // |join_wifi_button_| state is not updated here, it will be updated when
+  // WiFi device state changes.
+  delegate()->OnWifiToggleClicked(is_on);
+}
+
+void NetworkListWifiHeaderView::JoinWifiButtonPressed() {
+  base::RecordAction(base::UserMetricsAction("StatusArea_Network_JoinOther"));
+  Shell::Get()->system_tray_model()->client()->ShowNetworkCreate(
+      ::onc::network_type::kWiFi);
+}
+
+void NetworkListWifiHeaderView::SetJoinWifiButtonState(bool enabled,
+                                                       bool visible) {
+  if (!join_wifi_button_)
+    return;
+
+  join_wifi_button_->SetEnabled(enabled);
+  join_wifi_button_->SetVisible(visible);
+}
+
 }  // namespace ash
\ No newline at end of file
diff --git a/ash/system/network/network_list_wifi_header_view.h b/ash/system/network/network_list_wifi_header_view.h
index 1443721..3426798 100644
--- a/ash/system/network/network_list_wifi_header_view.h
+++ b/ash/system/network/network_list_wifi_header_view.h
@@ -6,11 +6,15 @@
 #define ASH_SYSTEM_NETWORK_NETWORK_LIST_WIFI_HEADER_VIEW_H_
 
 #include "ash/ash_export.h"
+#include "ash/style/icon_button.h"
 #include "ash/system/network/network_list_network_header_view.h"
+#include "ash/system/tray/tri_view.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/views/view.h"
 
 namespace ash {
 
-// This class is the interface used to create network list header for Wifi
+// This class is the implementation of the network list header for Wifi
 // networks, and is responsible for the creation of wifi-specific buttons.
 class ASH_EXPORT NetworkListWifiHeaderView
     : public NetworkListNetworkHeaderView {
@@ -22,7 +26,25 @@
       delete;
   ~NetworkListWifiHeaderView() override;
 
-  virtual void SetJoinWifiButtonState(bool enabled, bool visible) = 0;
+ private:
+  friend class NetworkListWifiHeaderViewTest;
+
+  // Used for testing.
+  static constexpr int kJoinWifiButtonId =
+      NetworkListNetworkHeaderView::kToggleButtonId + 1;
+
+  // NetworkListNetworkHeaderView:
+  void AddExtraButtons() override;
+  void SetToggleState(bool enabled, bool is_on) override;
+  void OnToggleToggled(bool is_on) override;
+
+  void JoinWifiButtonPressed();
+  void SetJoinWifiButtonState(bool enabled, bool visible);
+
+  // A button to invoke "Join Wi-Fi network" dialog.
+  IconButton* join_wifi_button_ = nullptr;
+
+  base::WeakPtrFactory<NetworkListWifiHeaderView> weak_factory_{this};
 };
 
 }  // namespace ash
diff --git a/ash/system/network/network_list_wifi_header_view_impl.cc b/ash/system/network/network_list_wifi_header_view_impl.cc
deleted file mode 100644
index 1328b6f3..0000000
--- a/ash/system/network/network_list_wifi_header_view_impl.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// 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 "ash/system/network/network_list_wifi_header_view_impl.h"
-
-#include "ash/constants/ash_features.h"
-#include "ash/public/cpp/system_tray_client.h"
-#include "ash/shell.h"
-#include "ash/strings/grit/ash_strings.h"
-#include "ash/style/icon_button.h"
-#include "ash/system/model/system_tray_model.h"
-#include "ash/system/network/network_list_network_header_view.h"
-#include "ash/system/network/network_list_wifi_header_view.h"
-#include "ash/system/network/tray_network_state_model.h"
-#include "ash/system/tray/tri_view.h"
-#include "base/memory/weak_ptr.h"
-#include "base/metrics/user_metrics.h"
-#include "chromeos/services/network_config/public/cpp/cros_network_config_util.h"
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
-#include "components/onc/onc_constants.h"
-#include "components/vector_icons/vector_icons.h"
-#include "ui/views/controls/image_view.h"
-#include "ui/views/view.h"
-
-namespace ash {
-namespace {
-using chromeos::network_config::mojom::DeviceStateType;
-using chromeos::network_config::mojom::NetworkType;
-}  // namespace
-
-NetworkListWifiHeaderViewImpl::NetworkListWifiHeaderViewImpl(
-    NetworkListNetworkHeaderView::Delegate* delegate)
-    : NetworkListWifiHeaderView(delegate) {
-  AddExtraButtons();
-}
-
-NetworkListWifiHeaderViewImpl::~NetworkListWifiHeaderViewImpl() = default;
-
-void NetworkListWifiHeaderViewImpl::AddExtraButtons() {
-  std::unique_ptr<IconButton> join_wifi_button = std::make_unique<IconButton>(
-      base::BindRepeating(&NetworkListWifiHeaderViewImpl::JoinWifiButtonPressed,
-                          weak_factory_.GetWeakPtr()),
-      IconButton::Type::kSmall, &vector_icons::kWifiAddIcon,
-      IDS_ASH_STATUS_TRAY_OTHER_WIFI);
-
-  join_wifi_button.get()->SetID(kJoinWifiButtonId);
-  join_wifi_button_ = join_wifi_button.get();
-  container()->AddView(TriView::Container::END, join_wifi_button.release());
-};
-
-void NetworkListWifiHeaderViewImpl::SetToggleState(bool enabled, bool is_on) {
-  join_wifi_button_->SetEnabled(enabled && is_on);
-  NetworkListNetworkHeaderView::SetToggleState(enabled, is_on);
-}
-
-void NetworkListWifiHeaderViewImpl::OnToggleToggled(bool is_on) {
-  // |join_wifi_button_| state is not updated here, it will be updated when
-  // WiFi device state changes.
-  delegate()->OnWifiToggleClicked(is_on);
-}
-
-void NetworkListWifiHeaderViewImpl::JoinWifiButtonPressed() {
-  base::RecordAction(base::UserMetricsAction("StatusArea_Network_JoinOther"));
-  Shell::Get()->system_tray_model()->client()->ShowNetworkCreate(
-      ::onc::network_type::kWiFi);
-}
-
-void NetworkListWifiHeaderViewImpl::SetJoinWifiButtonState(bool enabled,
-                                                           bool visible) {
-  if (!join_wifi_button_)
-    return;
-
-  join_wifi_button_->SetEnabled(enabled);
-  join_wifi_button_->SetVisible(visible);
-}
-
-}  // namespace ash
\ No newline at end of file
diff --git a/ash/system/network/network_list_wifi_header_view_impl.h b/ash/system/network/network_list_wifi_header_view_impl.h
deleted file mode 100644
index 8508bd9..0000000
--- a/ash/system/network/network_list_wifi_header_view_impl.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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 ASH_SYSTEM_NETWORK_NETWORK_LIST_WIFI_HEADER_VIEW_IMPL_H_
-#define ASH_SYSTEM_NETWORK_NETWORK_LIST_WIFI_HEADER_VIEW_IMPL_H_
-
-#include "ash/ash_export.h"
-#include "ash/style/icon_button.h"
-#include "ash/system/network/network_list_wifi_header_view.h"
-#include "ash/system/tray/tri_view.h"
-#include "base/memory/weak_ptr.h"
-#include "ui/views/view.h"
-
-namespace ash {
-
-// Implementation of NetworkListWifiHeaderView.
-class ASH_EXPORT NetworkListWifiHeaderViewImpl
-    : public NetworkListWifiHeaderView {
- public:
-  explicit NetworkListWifiHeaderViewImpl(
-      NetworkListNetworkHeaderView::Delegate* delegate);
-  NetworkListWifiHeaderViewImpl(const NetworkListWifiHeaderViewImpl&) = delete;
-  NetworkListWifiHeaderViewImpl& operator=(
-      const NetworkListWifiHeaderViewImpl&) = delete;
-  ~NetworkListWifiHeaderViewImpl() override;
-
- private:
-  friend class NetworkListWifiHeaderViewTest;
-
-  // Used for testing.
-  static constexpr int kJoinWifiButtonId =
-      NetworkListNetworkHeaderView::kToggleButtonId + 1;
-
-  // NetworkListNetworkHeaderView:
-  void AddExtraButtons() override;
-  void SetToggleState(bool enabled, bool is_on) override;
-  void OnToggleToggled(bool is_on) override;
-
-  // NetworkListWifiHeaderView:
-  void SetJoinWifiButtonState(bool enabled, bool visible) override;
-
-  void JoinWifiButtonPressed();
-
-  // A button to invoke "Join Wi-Fi network" dialog.
-  IconButton* join_wifi_button_ = nullptr;
-
-  base::WeakPtrFactory<NetworkListWifiHeaderViewImpl> weak_factory_{this};
-};
-
-}  // namespace ash
-
-#endif  // ASH_SYSTEM_NETWORK_NETWORK_LIST_WIFI_HEADER_VIEW_IMPL_H_
diff --git a/ash/system/network/network_list_wifi_header_view_unittest.cc b/ash/system/network/network_list_wifi_header_view_unittest.cc
index c9bd696..b56737a7 100644
--- a/ash/system/network/network_list_wifi_header_view_unittest.cc
+++ b/ash/system/network/network_list_wifi_header_view_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/system/network/network_list_wifi_header_view_impl.h"
+#include "ash/system/network/network_list_wifi_header_view.h"
 
 #include <memory>
 
@@ -36,10 +36,9 @@
     AshTestBase::SetUp();
     feature_list_.InitAndEnableFeature(features::kQuickSettingsNetworkRevamp);
 
-    std::unique_ptr<NetworkListWifiHeaderViewImpl>
-        network_list_wifi_header_view =
-            std::make_unique<NetworkListWifiHeaderViewImpl>(
-                &fake_network_list_network_header_delegate_);
+    std::unique_ptr<NetworkListWifiHeaderView> network_list_wifi_header_view =
+        std::make_unique<NetworkListWifiHeaderView>(
+            &fake_network_list_network_header_delegate_);
 
     widget_ = CreateFramelessTestWidget();
     widget_->SetFullscreen(true);
@@ -67,7 +66,7 @@
 
   IconButton* GetJoinWifiButton() {
     return FindViewById<IconButton*>(
-        NetworkListWifiHeaderViewImpl::kJoinWifiButtonId);
+        NetworkListWifiHeaderView::kJoinWifiButtonId);
   }
 
   TrayToggleButton* GetToggleButton() {
@@ -85,7 +84,7 @@
     return &fake_network_list_network_header_delegate_;
   }
 
-  NetworkListWifiHeaderViewImpl* network_list_wifi_header_view() {
+  NetworkListWifiHeaderView* network_list_wifi_header_view() {
     return network_list_wifi_header_view_;
   }
 
@@ -101,7 +100,7 @@
   base::test::ScopedFeatureList feature_list_;
   FakeNetworkListNetworkHeaderViewDelegate
       fake_network_list_network_header_delegate_;
-  NetworkListWifiHeaderViewImpl* network_list_wifi_header_view_;
+  NetworkListWifiHeaderView* network_list_wifi_header_view_;
 };
 
 TEST_F(NetworkListWifiHeaderViewTest, HeaderLabel) {
diff --git a/ash/system/toast/toast_manager_impl.cc b/ash/system/toast/toast_manager_impl.cc
index 142a4c4..eaa71ab 100644
--- a/ash/system/toast/toast_manager_impl.cc
+++ b/ash/system/toast/toast_manager_impl.cc
@@ -96,7 +96,8 @@
   overlay_ = std::make_unique<ToastOverlay>(
       this, current_toast_data_->text, current_toast_data_->dismiss_text,
       current_toast_data_->visible_on_lock_screen && locked_,
-      current_toast_data_->is_managed, current_toast_data_->dismiss_callback);
+      current_toast_data_->is_managed, current_toast_data_->dismiss_callback,
+      current_toast_data_->expired_callback);
   overlay_->Show(true);
 
   if (current_toast_data_->duration != ToastData::kInfiniteDuration) {
diff --git a/ash/system/toast/toast_manager_unittest.cc b/ash/system/toast/toast_manager_unittest.cc
index 054d11d6b..efb389a9 100644
--- a/ash/system/toast/toast_manager_unittest.cc
+++ b/ash/system/toast/toast_manager_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "components/session_manager/session_manager_types.h"
@@ -721,4 +722,77 @@
                                          duration, /*expected_count=*/1);
 }
 
+// Table-driven test that checks that a toast's expired callback is run when a
+// toast is closed when the toast manager cancels the toast, when the toast
+// duration cancels the toast, and when the dismiss button is pressed.
+TEST_F(ToastManagerImplTest, ExpiredCallbackRunsWhenToastOverlayClosed) {
+  // Covers possible ways that a toast can be cancelled.
+  enum class CancellationSource {
+    kToastManager,
+    kDismissButton,
+    kToastDuration,
+  };
+
+  struct {
+    const std::string scope_trace;
+    const CancellationSource source;
+  } kTestCases[] = {
+      {"Cancel toast through the toast manager",
+       CancellationSource::kToastManager},
+      {"Cancel toast by pressing the dismiss button",
+       CancellationSource::kDismissButton},
+      {"Cancel toast by letting duration elapse",
+       CancellationSource::kToastDuration},
+  };
+
+  auto* toast_manager = manager();
+
+  for (const auto& test_case : kTestCases) {
+    SCOPED_TRACE(test_case.scope_trace);
+    std::string toast_id = "TOAST_ID_" + base::NumberToString(GetToastSerial());
+
+    // Create data for a toast that matches the test case. If the test case is
+    // not `kToastDuration`, duration should be infinite, and if the test case
+    // is not `kDismissButton` then we do not need a dismiss button on the
+    // toast.
+    ToastData toast_data(
+        toast_id, ToastCatalogName::kToastManagerUnittest,
+        /*text=*/u"",
+        /*duration=*/test_case.source == CancellationSource::kToastDuration
+            ? ToastData::kDefaultToastDuration
+            : ToastData::kInfiniteDuration,
+        /*visible_on_lock_screen=*/false,
+        /*has_dismiss_button=*/test_case.source ==
+            CancellationSource::kDismissButton);
+
+    // Bind a lambda that will change a value to tell us whether the expired
+    // callback ran.
+    bool expired_callback_ran = false;
+    toast_data.expired_callback = base::BindLambdaForTesting(
+        [&expired_callback_ran]() { expired_callback_ran = true; });
+    toast_manager->Show(toast_data);
+
+    switch (test_case.source) {
+      case CancellationSource::kToastManager: {
+        toast_manager->Cancel(toast_id);
+        break;
+      }
+      case CancellationSource::kDismissButton: {
+        ClickDismissButton();
+        break;
+      }
+      case CancellationSource::kToastDuration: {
+        base::RunLoop run_loop;
+        base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+            FROM_HERE, run_loop.QuitClosure(),
+            ToastData::kDefaultToastDuration);
+        run_loop.Run();
+        break;
+      }
+    }
+
+    EXPECT_TRUE(expired_callback_ran);
+  }
+}
+
 }  // namespace ash
diff --git a/ash/system/toast/toast_overlay.cc b/ash/system/toast/toast_overlay.cc
index e9b97e2..a9d02a2 100644
--- a/ash/system/toast/toast_overlay.cc
+++ b/ash/system/toast/toast_overlay.cc
@@ -96,7 +96,8 @@
                            const std::u16string& dismiss_text,
                            bool show_on_lock_screen,
                            bool is_managed,
-                           base::RepeatingClosure dismiss_callback)
+                           base::RepeatingClosure dismiss_callback,
+                           base::RepeatingClosure expired_callback)
     : delegate_(delegate),
       text_(text),
       dismiss_text_(dismiss_text),
@@ -109,6 +110,7 @@
           is_managed)),
       display_observer_(std::make_unique<ToastDisplayObserver>(this)),
       dismiss_callback_(std::move(dismiss_callback)),
+      expired_callback_(std::move(expired_callback)),
       widget_size_(overlay_view_->GetPreferredSize()) {
   views::Widget::InitParams params;
   params.type = views::Widget::InitParams::TYPE_POPUP;
@@ -139,6 +141,8 @@
 ToastOverlay::~ToastOverlay() {
   keyboard::KeyboardUIController::Get()->RemoveObserver(this);
   overlay_widget_->Close();
+  if (expired_callback_)
+    expired_callback_.Run();
 }
 
 void ToastOverlay::Show(bool visible) {
diff --git a/ash/system/toast/toast_overlay.h b/ash/system/toast/toast_overlay.h
index 1bd41820..9c762a95 100644
--- a/ash/system/toast/toast_overlay.h
+++ b/ash/system/toast/toast_overlay.h
@@ -42,17 +42,21 @@
   // Offset of the overlay from the edge of the work area.
   static constexpr int kOffset = 16;
 
-  // Creates the Toast overlay UI. |text| is the message to be shown, and
-  // |dismiss_text| is the message for the button to dismiss the toast message.
-  // The dismiss button will only be displayed if |dismiss_text| is not empty.
-  // |dismiss_callback| will be called when the button is pressed.
-  // If |is_managed| is true, a managed icon will be added to the toast.
+  // Creates the Toast overlay UI. `text` is the message to be shown, and
+  // `dismiss_text` is the message for the button to dismiss the toast message.
+  // The dismiss button will only be displayed if `dismiss_text` is not empty.
+  // `dismiss_callback` will be called when the button is pressed.
+  // `expired_callback` will be called when the toast overlay is destroyed,
+  // regardless of whether the button was pressed. In other words,
+  // `expired_callback` is called whenever the toast disappears. If `is_managed`
+  // is true, a managed icon will be added to the toast.
   ToastOverlay(Delegate* delegate,
                const std::u16string& text,
                const std::u16string& dismiss_text,
                bool show_on_lock_screen,
                bool is_managed,
-               base::RepeatingClosure dismiss_callback);
+               base::RepeatingClosure dismiss_callback,
+               base::RepeatingClosure expired_callback);
 
   ToastOverlay(const ToastOverlay&) = delete;
   ToastOverlay& operator=(const ToastOverlay&) = delete;
@@ -95,6 +99,7 @@
   std::unique_ptr<SystemToastStyle> overlay_view_;
   std::unique_ptr<ToastDisplayObserver> display_observer_;
   base::RepeatingClosure dismiss_callback_;
+  base::RepeatingClosure expired_callback_;
 
   gfx::Size widget_size_;
 };
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_app.js b/ash/webui/diagnostics_ui/resources/diagnostics_app.js
index de66214..0ae9202 100644
--- a/ash/webui/diagnostics_ui/resources/diagnostics_app.js
+++ b/ash/webui/diagnostics_ui/resources/diagnostics_app.js
@@ -6,6 +6,7 @@
 import 'chrome://resources/ash/common/page_toolbar.js';
 import 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
 import './diagnostics_sticky_banner.js';
+import './diagnostics_shared_css.js';
 import './input_list.js';
 import './network_list.js';
 import './strings.m.js';
diff --git a/ash/webui/diagnostics_ui/resources/index.html b/ash/webui/diagnostics_ui/resources/index.html
index 6e400e8..7aaf0386 100644
--- a/ash/webui/diagnostics_ui/resources/index.html
+++ b/ash/webui/diagnostics_ui/resources/index.html
@@ -34,7 +34,6 @@
     <diagnostics-app></diagnostics-app>
 
     <script type="module" src="diagnostics_app.js"></script>
-    <link rel="stylesheet" src="diagnostics_shared_css.js"></script>
     <!-- Below mojo script required to run browser tests -->
     <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js">
     </script>
diff --git a/ash/webui/firmware_update_ui/resources/index.html b/ash/webui/firmware_update_ui/resources/index.html
index 5befd11..835a8f46 100644
--- a/ash/webui/firmware_update_ui/resources/index.html
+++ b/ash/webui/firmware_update_ui/resources/index.html
@@ -3,7 +3,10 @@
 found in the LICENSE file. -->
 <!DOCTYPE html>
 <html dir="$i18n{textdirection}" lang="$i18n{language}">
+<head>
   <meta name="color-scheme" content="light dark">
+  <meta charset="utf-8">
+  <title></title>
   <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
   <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
   <link rel="stylesheet" href="chrome://resources/chromeos/colors/cros_styles.css">
@@ -23,18 +26,13 @@
       }
     }
   </style>
-<head>
-    <title></title>
-    <meta charset="utf-8">
 </head>
 <body>
     <firmware-update-app></firmware-update-app>
 
-    <script type="module" src="firmware_update_app.js">
-    </script>
+    <script type="module" src="firmware_update_app.js"></script>
     <!-- Below mojo script required to run browser tests -->
     <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js">
     </script>
-    <link rel="stylesheet" src="firmware_shared_css.js">
 </body>
 </html>
diff --git a/ash/webui/os_feedback_ui/resources/index.html b/ash/webui/os_feedback_ui/resources/index.html
index a7453b6..99bb9c77 100644
--- a/ash/webui/os_feedback_ui/resources/index.html
+++ b/ash/webui/os_feedback_ui/resources/index.html
@@ -27,7 +27,6 @@
   <!-- Below mojo script required to run browser tests -->
   <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js">
   </script>
-  <link rel="stylesheet" src="os_feedback_shared_css.js">
 </body>
 
 </html>
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_albums_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_albums_element.html
index d97bd065..8a095b9f 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_albums_element.html
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_albums_element.html
@@ -15,6 +15,7 @@
     scroll-target="gridScrollThreshold">
     <template>
       <wallpaper-grid-item
+        aria-label$="[[getAlbumAriaLabel_(album)]]"
         class="album"
         image-src="[[album.preview.url]]"
         index="[[index]]"
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_albums_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_albums_element.ts
index ecae1aa..7d8fc72 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_albums_element.ts
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_albums_element.ts
@@ -198,6 +198,15 @@
     afterNextRender(this, () => this.$.grid.fire('iron-resize'));
   }
 
+  /** Returns the aria label for the specified |album|. */
+  private getAlbumAriaLabel_(album: GooglePhotosAlbum|null): string|undefined {
+    if (album) {
+      return album.id === PLACEHOLDER_ID ? this.i18n('ariaLabelLoading') :
+                                           album.title;
+    }
+    return undefined;
+  }
+
   /** Returns the secondary text to display for the specified |album|. */
   private getSecondaryText_(album: GooglePhotosAlbum): string {
     return getCountText(album.photoCount);
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.html
index fd64a628..92fe7a9 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.html
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.html
@@ -15,6 +15,7 @@
     scroll-target="gridScrollThreshold">
     <template>
       <wallpaper-grid-item
+        aria-label$="[[getPhotoAriaLabel_(photo)]]"
         class="photo"
         image-src="[[photo.url.url]]"
         index="[[index]]"
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.ts
index 59fb5887..3e2641d 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.ts
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.ts
@@ -276,6 +276,15 @@
     }
   }
 
+  /** Returns the aria label for the specified |photo|. */
+  private getPhotoAriaLabel_(photo: GooglePhotosPhoto|null): string|undefined {
+    if (photo) {
+      return photo.id === PLACEHOLDER_ID ? this.i18n('ariaLabelLoading') :
+                                           photo.name;
+    }
+    return undefined;
+  }
+
   /** Returns whether the specified |photo| is a placeholder. */
   private isPhotoPlaceholder_(photo: GooglePhotosPhoto|null): boolean {
     return !!photo && photo.id === PLACEHOLDER_ID;
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.html
index a29d0ee..02d43f1 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.html
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.html
@@ -35,7 +35,7 @@
   .location {
     color: var(--cros-text-color-disabled);
     font-weight: 400;
-    padding-left: 12px;
+    padding-inline-start: 12px;
   }
 
   .photos {
@@ -63,6 +63,7 @@
         <div class="photos">
           <template is="dom-repeat" items="[[row]]" as="photo">
             <wallpaper-grid-item
+              aria-label$="[[getPhotoAriaLabel_(photo)]]"
               class="photo"
               colindex$="[[index]]"
               image-src="[[photo.url.url]]"
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.ts
index 4aebf879..f41719b8 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.ts
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.ts
@@ -398,7 +398,7 @@
     return sections;
   }
 
-  // Returns the date to display for the specified grid |row|.
+  /** Returns the date to display for the specified grid |row|. */
   private getGridRowDate_(
       row: GooglePhotosPhotosRow,
       photosBySection: GooglePhotosPhotos['photosBySection_']): string
@@ -411,7 +411,7 @@
     return gridRowSection ? gridRowSection.date : undefined;
   }
 
-  // Returns the locations to display for the specified grid |row|.
+  /** Returns the locations to display for the specified grid |row|. */
   private getGridRowLocations_(
       row: GooglePhotosPhotosRow,
       photosBySection: GooglePhotosPhotos['photosBySection_']): string
@@ -426,7 +426,16 @@
         undefined;
   }
 
-  // Returns whether the title for the specified grid |row| is visible.
+  /** Returns the aria label for the specified |photo|. */
+  private getPhotoAriaLabel_(photo: GooglePhotosPhoto|null): string|undefined {
+    if (photo) {
+      return photo.id === PLACEHOLDER_ID ? this.i18n('ariaLabelLoading') :
+                                           photo.name;
+    }
+    return undefined;
+  }
+
+  /** Returns whether the title for the specified grid |row| is visible. */
   private isGridRowTitleVisible_(
       row: GooglePhotosPhotosRow,
       photosBySection: GooglePhotosPhotos['photosBySection_']): boolean {
@@ -438,7 +447,7 @@
     return !!photo && photo.id === PLACEHOLDER_ID;
   }
 
-  // Returns whether the specified |photo| is currently selected.
+  /** Returns whether the specified |photo| is currently selected. */
   private isPhotoSelected_(
       photo: GooglePhotosPhoto|null,
       currentSelected: GooglePhotosPhotos['currentSelected_'],
diff --git a/ash/webui/print_management/resources/index.html b/ash/webui/print_management/resources/index.html
index 874e06c..123cdf27 100644
--- a/ash/webui/print_management/resources/index.html
+++ b/ash/webui/print_management/resources/index.html
@@ -21,8 +21,6 @@
     <print-management></print-management>
     <script type="module" src="print_management.js"></script>
     <script type="module" src="mojo_interface_provider.js"></script>
-    <link rel="stylesheet" src="print_management_shared_css.js"></script>
-    <link rel="stylesheet" src="print_management_fonts_css.js"></script>
     <!-- Below mojo script required to run browser tests -->
     <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js">
     </script>
diff --git a/ash/webui/scanning/resources/index.html b/ash/webui/scanning/resources/index.html
index b21394b..94811a7b 100644
--- a/ash/webui/scanning/resources/index.html
+++ b/ash/webui/scanning/resources/index.html
@@ -28,7 +28,6 @@
 
     <script type="module" src="scanning_app.js"></script>
     <script type="module" src="mojo_interface_provider.js"></script>
-    <link rel="stylesheet" src="scanning_shared_css.js"></script>
     <!-- Below mojo script required to run browser tests -->
     <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js">
     </script>
diff --git a/ash/webui/shimless_rma/resources/index.html b/ash/webui/shimless_rma/resources/index.html
index c9025702..d7b997c 100644
--- a/ash/webui/shimless_rma/resources/index.html
+++ b/ash/webui/shimless_rma/resources/index.html
@@ -21,8 +21,6 @@
   <body>
     <shimless-rma></shimless-rma>
 
-    <link rel="stylesheet" src="shimless_rma_shared_css.js">
-    <link rel="stylesheet" src="shimless_rma_fonts_css.js">
     <script type="module" src="shimless_rma.js"></script>
     <!-- Below mojo script required to run browser tests -->
     <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js">
diff --git a/base/BUILD.gn b/base/BUILD.gn
index e44e75b..f0a01d4 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -3984,6 +3984,7 @@
     ]
 
     deps = [
+      "//build/android:build_java",
       "//third_party/android_deps:com_google_code_findbugs_jsr305_java",
       "//third_party/androidx:androidx_annotation_annotation_experimental_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
@@ -3992,10 +3993,7 @@
       "//third_party/androidx:androidx_multidex_multidex_java",
     ]
 
-    public_deps = [
-      ":jni_java",
-      "//build/android:build_java",
-    ]
+    public_deps = [ ":jni_java" ]
 
     sources = [
       "android/java/src/org/chromium/base/ActivityState.java",
@@ -4174,6 +4172,7 @@
       ":base_java",
       ":base_java_test_support",
       "//base/test:test_support_java",
+      "//build/android:build_java",
       "//third_party/android_support_test_runner:runner_java",
       "//third_party/androidx:androidx_test_runner_java",
       "//third_party/hamcrest:hamcrest_java",
@@ -4228,6 +4227,7 @@
 
     deps = [
       ":base_java",
+      "//build/android:build_java",
       "//third_party/android_sdk:android_test_base_java",
       "//third_party/android_sdk:android_test_mock_java",
       "//third_party/android_support_test_runner:runner_java",
@@ -4323,7 +4323,10 @@
   android_library("base_java_process_launcher_test_support") {
     testonly = true
 
-    deps = [ ":base_java" ]
+    deps = [
+      ":base_java",
+      "//build/android:build_java",
+    ]
 
     sources = [ "test/android/javatests/src/org/chromium/base/process_launcher/TestChildProcessConnection.java" ]
   }
@@ -4350,6 +4353,7 @@
 
     deps = [
       ":base_java",
+      "//build/android:build_java",
       "//testing/android/junit:junit_test_support",
       "//third_party/android_deps:robolectric_all_java",
       "//third_party/android_support_test_runner:runner_java",
@@ -4417,6 +4421,7 @@
       ":base_junit_test_support",
       ":jni_java",
       "//base/test:test_support_java",
+      "//build/android:build_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
       "//third_party/androidx:androidx_test_runner_java",
       "//third_party/hamcrest:hamcrest_java",
@@ -4452,13 +4457,19 @@
 
     annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 
-    deps = [ "//base:base_java" ]
+    deps = [
+      "//base:base_java",
+      "//build/android:build_java",
+    ]
   }
 
   android_library("base_java_unittest_support") {
     testonly = true
 
-    deps = [ ":base_java" ]
+    deps = [
+      ":base_java",
+      "//build/android:build_java",
+    ]
 
     sources = [
       "test/android/java/src/org/chromium/base/ContentUriTestUtils.java",
diff --git a/base/android/jni_generator/BUILD.gn b/base/android/jni_generator/BUILD.gn
index a7446de..e58e9a4 100644
--- a/base/android/jni_generator/BUILD.gn
+++ b/base/android/jni_generator/BUILD.gn
@@ -20,7 +20,10 @@
     "java/src/org/chromium/example/jni_generator/SampleForTests.java",
   ]
 
-  deps = [ "//base:base_java" ]
+  deps = [
+    "//base:base_java",
+    "//build/android:build_java",
+  ]
 
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
@@ -28,7 +31,10 @@
 android_library("jni_annotation_sample_java") {
   sources = [ "java/src/org/chromium/example/jni_generator/SampleForAnnotationProcessor.java" ]
 
-  deps = [ "//base:base_java" ]
+  deps = [
+    "//base:base_java",
+    "//build/android:build_java",
+  ]
 
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
@@ -63,6 +69,7 @@
   deps = [
     ":jni_sample_java",
     "//base:base_java",
+    "//build/android:build_java",
   ]
   shared_libraries = [ ":jni_sample_lib" ]
   jni_registration_header = _registration_header
diff --git a/base/ranges/algorithm.h b/base/ranges/algorithm.h
index a4ab025..1f80726 100644
--- a/base/ranges/algorithm.h
+++ b/base/ranges/algorithm.h
@@ -63,9 +63,9 @@
 
  private:
   template <typename ProjT, typename ProjU, typename T, typename U>
-  using InvokeResult = invoke_result_t<Pred&,
-                                       invoke_result_t<ProjT&, T&&>,
-                                       invoke_result_t<ProjU&, U&&>>;
+  using InvokeResult = std::invoke_result_t<Pred&,
+                                            std::invoke_result_t<ProjT&, T&&>,
+                                            std::invoke_result_t<ProjU&, U&&>>;
 
   template <typename T, typename U, typename = InvokeResult<Proj1, Proj2, T, U>>
   constexpr std::pair<Proj1&, Proj2&> GetProjs(priority_tag<3>) const {
diff --git a/base/task/thread_pool/job_task_source.cc b/base/task/thread_pool/job_task_source.cc
index f2cfb7c..75cb72c 100644
--- a/base/task/thread_pool/job_task_source.cc
+++ b/base/task/thread_pool/job_task_source.cc
@@ -30,8 +30,9 @@
 constexpr size_t kMaxWorkersPerJob = 32;
 static_assert(
     kMaxWorkersPerJob <=
-        std::numeric_limits<base::invoke_result<
-            decltype (&JobDelegate::GetTaskId), JobDelegate>::type>::max(),
+        std::numeric_limits<
+            std::invoke_result<decltype(&JobDelegate::GetTaskId),
+                               JobDelegate>::type>::max(),
     "AcquireTaskId return type isn't big enough to fit kMaxWorkersPerJob");
 
 }  // namespace
diff --git a/base/template_util.h b/base/template_util.h
index 8f4de74..e319a7ed 100644
--- a/base/template_util.h
+++ b/base/template_util.h
@@ -237,58 +237,6 @@
 template <typename B>
 struct negation : bool_constant<!static_cast<bool>(B::value)> {};
 
-// Implementation of C++17's invoke_result.
-//
-// This implementation adds references to `Functor` and `Args` to work around
-// some quirks of std::result_of. See the #Notes section of [1] for details.
-//
-// References:
-// [1] https://en.cppreference.com/w/cpp/types/result_of
-// [2] https://wg21.link/meta.trans.other#lib:invoke_result
-template <typename Functor, typename... Args>
-using invoke_result = std::invoke_result<Functor, Args...>;
-
-// Implementation of C++17's std::invoke_result_t.
-//
-// Reference: https://wg21.link/meta.type.synop#lib:invoke_result_t
-template <typename Functor, typename... Args>
-using invoke_result_t = typename invoke_result<Functor, Args...>::type;
-
-namespace internal {
-
-// Base case, `InvokeResult` does not have a nested type member. This means `F`
-// could not be invoked with `Args...` and thus is not invocable.
-template <typename InvokeResult, typename R, typename = void>
-struct IsInvocableImpl : std::false_type {};
-
-// Happy case, `InvokeResult` does have a nested type member. Now check whether
-// `InvokeResult::type` is convertible to `R`. Short circuit in case
-// `std::is_void<R>`.
-template <typename InvokeResult, typename R>
-struct IsInvocableImpl<InvokeResult, R, void_t<typename InvokeResult::type>>
-    : disjunction<std::is_void<R>,
-                  std::is_convertible<typename InvokeResult::type, R>> {};
-
-}  // namespace internal
-
-// Implementation of C++17's std::is_invocable_r.
-//
-// Returns whether `F` can be invoked with `Args...` and the result is
-// convertible to `R`.
-//
-// Reference: https://wg21.link/meta.rel#lib:is_invocable_r
-template <typename R, typename F, typename... Args>
-struct is_invocable_r
-    : internal::IsInvocableImpl<invoke_result<F, Args...>, R> {};
-
-// Implementation of C++17's std::is_invocable.
-//
-// Returns whether `F` can be invoked with `Args...`.
-//
-// Reference: https://wg21.link/meta.rel#lib:is_invocable
-template <typename F, typename... Args>
-struct is_invocable : is_invocable_r<void, F, Args...> {};
-
 namespace internal {
 
 // The indirection with std::is_enum<T> is required, because instantiating
@@ -363,7 +311,8 @@
 //
 // Reference: https://wg21.link/iterator.synopsis#:~:text=indirect_result_t
 template <typename Func, typename... Iters>
-using indirect_result_t = invoke_result_t<Func, iter_reference_t<Iters>...>;
+using indirect_result_t =
+    std::invoke_result_t<Func, iter_reference_t<Iters>...>;
 
 // Simplified implementation of C++20's std::projected. As opposed to
 // std::projected, this implementation does not explicitly restrict the type of
diff --git a/base/template_util_unittest.cc b/base/template_util_unittest.cc
index af1d269e..7f78f21 100644
--- a/base/template_util_unittest.cc
+++ b/base/template_util_unittest.cc
@@ -184,62 +184,6 @@
 static_assert(negation<negation<TrueT>>::value, "");
 static_assert(!negation<negation<FalseT>>::value, "");
 
-// is_invocable
-TEST(TemplateUtil, IsInvocable) {
-  struct Base {};
-  struct Derived : Base {};
-
-  struct Implicit {
-    Implicit(int) {}
-  };
-
-  struct Explicit {
-    explicit Explicit(int) {}
-  };
-
-  struct CallableWithBaseButNotWithInt {
-    int operator()(int) = delete;
-    int operator()(Base) { return 42; }
-  };
-
-  {
-    using Fp = void (*)(Base&, int);
-    static_assert(is_invocable<Fp, Base&, int>::value, "");
-    static_assert(is_invocable<Fp, Derived&, int>::value, "");
-    static_assert(!is_invocable<Fp, const Base&, int>::value, "");
-    static_assert(!is_invocable<Fp>::value, "");
-    static_assert(!is_invocable<Fp, Base&>::value, "");
-  }
-  {
-    // Function reference
-    using Fp = void (&)(Base&, int);
-    static_assert(is_invocable<Fp, Base&, int>::value, "");
-    static_assert(is_invocable<Fp, Derived&, int>::value, "");
-    static_assert(!is_invocable<Fp, const Base&, int>::value, "");
-    static_assert(!is_invocable<Fp>::value, "");
-    static_assert(!is_invocable<Fp, Base&>::value, "");
-  }
-  {
-    // Function object
-    using Fn = CallableWithBaseButNotWithInt;
-    static_assert(is_invocable<Fn, Base>::value, "");
-    static_assert(!is_invocable<Fn, int>::value, "");
-  }
-  {
-    // Check that the conversion to the return type is properly checked
-    using Fn = int (*)(int);
-    static_assert(is_invocable_r<Implicit, Fn, int>::value, "");
-    static_assert(is_invocable_r<double, Fn, int>::value, "");
-    static_assert(is_invocable_r<const volatile void, Fn, int>::value, "");
-    static_assert(!is_invocable_r<Explicit, Fn, int>::value, "");
-
-    static_assert(is_invocable_r<Implicit, Fn, double>::value, "");
-    static_assert(!is_invocable_r<double, Fn, std::string>::value, "");
-    static_assert(is_invocable_r<const volatile void, Fn, double>::value, "");
-    static_assert(!is_invocable_r<Explicit, Fn, double>::value, "");
-  }
-}
-
 // is_scoped_enum
 TEST(TemplateUtil, IsScopedEnum) {
   static_assert(!is_scoped_enum<int>::value, "");
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index 40aab7e..6a6f6c92 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -391,6 +391,7 @@
 
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//testing/android/native_test:native_main_runner_java",
       "//third_party/android_deps:com_google_code_findbugs_jsr305_java",
     ]
diff --git a/base/threading/hang_watcher.h b/base/threading/hang_watcher.h
index de665fc..e2d3e16 100644
--- a/base/threading/hang_watcher.h
+++ b/base/threading/hang_watcher.h
@@ -491,8 +491,8 @@
 
  private:
   using TimeTicksInternalRepresentation =
-      base::invoke_result<decltype(&TimeTicks::ToInternalValue),
-                          TimeTicks>::type;
+      std::invoke_result<decltype(&TimeTicks::ToInternalValue),
+                         TimeTicks>::type;
   static_assert(std::is_same<TimeTicksInternalRepresentation, int64_t>::value,
                 "Bit manipulations made by HangWatchDeadline need to be"
                 "adapted if internal representation of TimeTicks changes.");
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 0ca23f5..454fe05 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -3999,6 +3999,7 @@
       if (!defined(use_default_launcher) || use_default_launcher) {
         deps += [
           "//base:base_java",
+          "//build/android:build_java",
           "//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
           "//testing/android/native_test:native_test_java",
         ]
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 83b06b94..07ce2387 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-8.20220427.1.1
+8.20220427.2.1
diff --git a/cc/metrics/compositor_frame_reporter.cc b/cc/metrics/compositor_frame_reporter.cc
index d3ecb6b..e5589837 100644
--- a/cc/metrics/compositor_frame_reporter.cc
+++ b/cc/metrics/compositor_frame_reporter.cc
@@ -320,18 +320,19 @@
 CompositorFrameReporter::CompositorFrameReporter(
     const ActiveTrackers& active_trackers,
     const viz::BeginFrameArgs& args,
-    bool should_report_metrics,
+    bool should_report_histograms,
     SmoothThread smooth_thread,
     FrameInfo::SmoothEffectDrivingThread scrolling_thread,
     int layer_tree_host_id,
     const GlobalMetricsTrackers& trackers)
-    : should_report_metrics_(should_report_metrics),
+    : should_report_histograms_(should_report_histograms),
       args_(args),
       active_trackers_(active_trackers),
       scrolling_thread_(scrolling_thread),
       smooth_thread_(smooth_thread),
       layer_tree_host_id_(layer_tree_host_id),
       global_trackers_(trackers) {
+  DCHECK(global_trackers_.dropped_frame_counter);
   global_trackers_.dropped_frame_counter->OnBeginFrame(
       args, IsScrollActive(active_trackers_));
   DCHECK(IsScrollActive(active_trackers_) ||
@@ -483,7 +484,7 @@
     return nullptr;
   }
   auto new_reporter = std::make_unique<CompositorFrameReporter>(
-      active_trackers_, args_, should_report_metrics_, smooth_thread_,
+      active_trackers_, args_, should_report_histograms_, smooth_thread_,
       scrolling_thread_, layer_tree_host_id_, global_trackers_);
   new_reporter->did_finish_impl_frame_ = did_finish_impl_frame_;
   new_reporter->impl_frame_finish_time_ = impl_frame_finish_time_;
@@ -647,8 +648,9 @@
   if (TestReportType(FrameReportType::kNonDroppedFrame))
     ReportEventLatencyTraceEvents();
 
-  // Only report compositor latency histograms if the frame was produced.
-  if (should_report_metrics_ && report_types_.any()) {
+  // Only report compositor latency metrics if the frame was produced.
+  if (report_types_.any() &&
+      (should_report_histograms_ || global_trackers_.latency_ukm_reporter)) {
     DCHECK(stage_history_.size());
     DCHECK_EQ(SumOfStageHistory(), stage_history_.back().end_time -
                                        stage_history_.front().start_time);
@@ -656,25 +658,21 @@
                                 stage_history_.front().start_time,
                                 stage_history_.back().end_time);
 
-    ReportCompositorLatencyHistograms();
-    // Only report event latency histograms if the frame was presented.
+    ReportCompositorLatencyMetrics();
+    // Only report event latency metrics if the frame was presented.
     if (TestReportType(FrameReportType::kNonDroppedFrame))
-      ReportEventLatencyHistograms();
+      ReportEventLatencyMetrics();
   }
 
-  auto* dropped_frame_counter = global_trackers_.dropped_frame_counter;
-  if (dropped_frame_counter) {
-    if (TestReportType(FrameReportType::kDroppedFrame)) {
-      dropped_frame_counter->AddDroppedFrame();
-    } else {
-      if (has_partial_update_)
-        dropped_frame_counter->AddPartialFrame();
-      else
-        dropped_frame_counter->AddGoodFrame();
-    }
-
-    dropped_frame_counter->OnEndFrame(args_, frame_info);
+  if (TestReportType(FrameReportType::kDroppedFrame)) {
+    global_trackers_.dropped_frame_counter->AddDroppedFrame();
+  } else {
+    if (has_partial_update_)
+      global_trackers_.dropped_frame_counter->AddPartialFrame();
+    else
+      global_trackers_.dropped_frame_counter->AddGoodFrame();
   }
+  global_trackers_.dropped_frame_counter->OnEndFrame(args_, frame_info);
 
   if (discarded_partial_update_dependents_count_ > 0)
     UMA_HISTOGRAM_CUSTOM_COUNTS(
@@ -690,10 +688,20 @@
   current_stage_.start_time = base::TimeTicks();
 }
 
-void CompositorFrameReporter::ReportCompositorLatencyHistograms() const {
+void CompositorFrameReporter::ReportCompositorLatencyMetrics() const {
   static base::CpuReductionExperimentFilter filter;
   if (!filter.ShouldLogHistograms())
     return;
+
+  if (global_trackers_.latency_ukm_reporter) {
+    global_trackers_.latency_ukm_reporter->ReportCompositorLatencyUkm(
+        report_types_, stage_history_, active_trackers_,
+        *processed_blink_breakdown_, *processed_viz_breakdown_);
+  }
+
+  if (!should_report_histograms_)
+    return;
+
   for (const StageData& stage : stage_history_) {
     ReportStageHistogramWithBreakdown(stage);
 
@@ -708,12 +716,6 @@
     }
   }
 
-  if (global_trackers_.latency_ukm_reporter) {
-    global_trackers_.latency_ukm_reporter->ReportCompositorLatencyUkm(
-        report_types_, stage_history_, active_trackers_,
-        *processed_blink_breakdown_, *processed_viz_breakdown_);
-  }
-
   for (size_t type = 0; type < report_types_.size(); ++type) {
     if (!report_types_.test(type))
       continue;
@@ -884,10 +886,19 @@
   }
 }
 
-void CompositorFrameReporter::ReportEventLatencyHistograms() const {
+void CompositorFrameReporter::ReportEventLatencyMetrics() const {
   const StageData& total_latency_stage = stage_history_.back();
   DCHECK_EQ(StageType::kTotalLatency, total_latency_stage.stage_type);
 
+  if (global_trackers_.latency_ukm_reporter) {
+    global_trackers_.latency_ukm_reporter->ReportEventLatencyUkm(
+        events_metrics_, stage_history_, *processed_blink_breakdown_,
+        *processed_viz_breakdown_);
+  }
+
+  if (!should_report_histograms_)
+    return;
+
   const std::string total_latency_stage_name =
       GetStageName(StageType::kTotalLatency);
   const std::string total_latency_histogram_name =
@@ -935,12 +946,6 @@
         total_latency_histogram_name, total_latency, kEventLatencyHistogramMin,
         kEventLatencyHistogramMax, kEventLatencyHistogramBucketCount);
   }
-
-  if (global_trackers_.latency_ukm_reporter) {
-    global_trackers_.latency_ukm_reporter->ReportEventLatencyUkm(
-        events_metrics_, stage_history_, *processed_blink_breakdown_,
-        *processed_viz_breakdown_);
-  }
 }
 
 void CompositorFrameReporter::ReportCompositorLatencyTraceEvents(
diff --git a/cc/metrics/compositor_frame_reporter.h b/cc/metrics/compositor_frame_reporter.h
index f903e3d2..230bafc 100644
--- a/cc/metrics/compositor_frame_reporter.h
+++ b/cc/metrics/compositor_frame_reporter.h
@@ -36,9 +36,9 @@
 class LatencyUkmReporter;
 
 struct GlobalMetricsTrackers {
-  DroppedFrameCounter* dropped_frame_counter = nullptr;
-  LatencyUkmReporter* latency_ukm_reporter = nullptr;
-  FrameSequenceTrackerCollection* frame_sequence_trackers = nullptr;
+  raw_ptr<DroppedFrameCounter> dropped_frame_counter = nullptr;
+  raw_ptr<LatencyUkmReporter> latency_ukm_reporter = nullptr;
+  raw_ptr<FrameSequenceTrackerCollection> frame_sequence_trackers = nullptr;
 };
 
 // This is used for tracing and reporting the duration of pipeline stages within
@@ -228,7 +228,7 @@
 
   CompositorFrameReporter(const ActiveTrackers& active_trackers,
                           const viz::BeginFrameArgs& args,
-                          bool should_report_metrics,
+                          bool should_report_histograms,
                           SmoothThread smooth_thread,
                           FrameInfo::SmoothEffectDrivingThread scrolling_thread,
                           int layer_tree_host_id,
@@ -350,7 +350,7 @@
   void TerminateReporter();
   void EndCurrentStage(base::TimeTicks end_time);
 
-  void ReportCompositorLatencyHistograms() const;
+  void ReportCompositorLatencyMetrics() const;
   void ReportStageHistogramWithBreakdown(
       const StageData& stage,
       FrameSequenceTrackerType frame_sequence_tracker_type =
@@ -366,7 +366,7 @@
       absl::optional<BlinkBreakdown> blink_breakdown,
       base::TimeDelta time_delta) const;
 
-  void ReportEventLatencyHistograms() const;
+  void ReportEventLatencyMetrics() const;
   void ReportCompositorLatencyTraceEvents(const FrameInfo& info) const;
   void ReportEventLatencyTraceEvents() const;
 
@@ -389,7 +389,9 @@
 
   base::WeakPtr<CompositorFrameReporter> GetWeakPtr();
 
-  const bool should_report_metrics_;
+  // Whether UMA histograms should be reported or not.
+  const bool should_report_histograms_;
+
   const viz::BeginFrameArgs args_;
 
   StageData current_stage_;
diff --git a/cc/metrics/compositor_frame_reporting_controller.cc b/cc/metrics/compositor_frame_reporting_controller.cc
index fbf02b1..c40ffce 100644
--- a/cc/metrics/compositor_frame_reporting_controller.cc
+++ b/cc/metrics/compositor_frame_reporting_controller.cc
@@ -26,12 +26,17 @@
 }  // namespace
 
 CompositorFrameReportingController::CompositorFrameReportingController(
-    bool should_report_metrics,
+    bool should_report_histograms,
+    bool should_report_ukm,
     int layer_tree_host_id)
-    : should_report_metrics_(should_report_metrics),
+    : should_report_histograms_(should_report_histograms),
       layer_tree_host_id_(layer_tree_host_id),
       latency_ukm_reporter_(std::make_unique<LatencyUkmReporter>()) {
-  global_trackers_.latency_ukm_reporter = latency_ukm_reporter_.get();
+  if (should_report_ukm) {
+    // UKM metrics should be reported if and only if `latency_ukm_reporter` is
+    // set on `global_trackers_`.
+    global_trackers_.latency_ukm_reporter = latency_ukm_reporter_.get();
+  }
 }
 
 CompositorFrameReportingController::~CompositorFrameReportingController() {
@@ -107,7 +112,7 @@
     }
   }
   auto reporter = std::make_unique<CompositorFrameReporter>(
-      active_trackers_, args, should_report_metrics_, GetSmoothThread(),
+      active_trackers_, args, should_report_histograms_, GetSmoothThread(),
       scrolling_thread_, layer_tree_host_id_, global_trackers_);
   reporter->set_tick_clock(tick_clock_);
   reporter->StartStage(StageType::kBeginImplFrameToSendBeginMainFrame,
@@ -145,7 +150,7 @@
       smooth_thread = last_started_compositor_frame_.smooth_thread;
     }
     auto reporter = std::make_unique<CompositorFrameReporter>(
-        active_trackers, args, should_report_metrics_, smooth_thread,
+        active_trackers, args, should_report_histograms_, smooth_thread,
         scrolling_thread, layer_tree_host_id_, global_trackers_);
     reporter->set_tick_clock(tick_clock_);
     reporter->StartStage(StageType::kSendBeginMainFrameToCommit, Now());
@@ -729,7 +734,7 @@
     // start time, but they were skipped and history of scrolling thread might
     // change in the diff of start time and report time.
     auto reporter = std::make_unique<CompositorFrameReporter>(
-        active_trackers_, args, should_report_metrics_,
+        active_trackers_, args, should_report_histograms_,
         GetSmoothThreadAtTime(timestamp),
         FrameInfo::SmoothEffectDrivingThread::kUnknown, layer_tree_host_id_,
         global_trackers_);
diff --git a/cc/metrics/compositor_frame_reporting_controller.h b/cc/metrics/compositor_frame_reporting_controller.h
index ee9cfff..680cbe8 100644
--- a/cc/metrics/compositor_frame_reporting_controller.h
+++ b/cc/metrics/compositor_frame_reporting_controller.h
@@ -45,7 +45,8 @@
     kNumPipelineStages
   };
 
-  CompositorFrameReportingController(bool should_report_metrics,
+  CompositorFrameReportingController(bool should_report_histograms,
+                                     bool should_report_ukm,
                                      int layer_tree_host_id);
   virtual ~CompositorFrameReportingController();
 
@@ -166,7 +167,7 @@
   void AddSortedFrame(const viz::BeginFrameArgs& args,
                       const FrameInfo& frame_info);
 
-  const bool should_report_metrics_;
+  const bool should_report_histograms_;
   const int layer_tree_host_id_;
 
   viz::BeginFrameId last_submitted_frame_id_;
diff --git a/cc/metrics/compositor_frame_reporting_controller_unittest.cc b/cc/metrics/compositor_frame_reporting_controller_unittest.cc
index 524f144d..7a263cd69 100644
--- a/cc/metrics/compositor_frame_reporting_controller_unittest.cc
+++ b/cc/metrics/compositor_frame_reporting_controller_unittest.cc
@@ -34,7 +34,8 @@
     : public CompositorFrameReportingController {
  public:
   TestCompositorFrameReportingController()
-      : CompositorFrameReportingController(/*should_report_metrics=*/true,
+      : CompositorFrameReportingController(/*should_report_histograms=*/true,
+                                           /*should_report_ukm=*/false,
                                            /*layer_tree_host_id=*/1) {}
 
   TestCompositorFrameReportingController(
diff --git a/cc/metrics/frame_sequence_tracker_unittest.cc b/cc/metrics/frame_sequence_tracker_unittest.cc
index cb3c6d72..e1f7b45 100644
--- a/cc/metrics/frame_sequence_tracker_unittest.cc
+++ b/cc/metrics/frame_sequence_tracker_unittest.cc
@@ -13,9 +13,6 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "cc/metrics/compositor_frame_reporting_controller.h"
 #include "cc/metrics/frame_sequence_tracker_collection.h"
-#include "cc/metrics/throughput_ukm_reporter.h"
-#include "cc/trees/ukm_manager.h"
-#include "components/ukm/test_ukm_recorder.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -45,7 +42,8 @@
   FrameSequenceTrackerTest()
       : compositor_frame_reporting_controller_(
             std::make_unique<CompositorFrameReportingController>(
-                /*should_report_metrics=*/true,
+                /*should_report_histograms=*/true,
+                /*should_report_ukm=*/false,
                 /*layer_tree_host_id=*/1)),
         collection_(/*is_single_threaded=*/false,
                     compositor_frame_reporting_controller_.get()) {
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc
index 31df8af..42097da 100644
--- a/cc/raster/one_copy_raster_buffer_provider.cc
+++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -413,7 +413,7 @@
 
   // Create staging shared image.
   if (staging_buffer->mailbox.IsZero()) {
-    const uint32_t usage = gpu::SHARED_IMAGE_USAGE_RASTER;
+    const uint32_t usage = gpu::SHARED_IMAGE_USAGE_CPU_WRITE;
     staging_buffer->mailbox = sii->CreateSharedImage(
         staging_buffer->gpu_memory_buffer.get(), gpu_memory_buffer_manager_,
         color_space, kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, usage);
diff --git a/cc/test/fake_compositor_frame_reporting_controller.cc b/cc/test/fake_compositor_frame_reporting_controller.cc
index 3c91e4b..6d391ef 100644
--- a/cc/test/fake_compositor_frame_reporting_controller.cc
+++ b/cc/test/fake_compositor_frame_reporting_controller.cc
@@ -13,7 +13,8 @@
 base::TimeDelta INTERVAL = base::Milliseconds(16);
 
 FakeCompositorFrameReportingController::FakeCompositorFrameReportingController()
-    : CompositorFrameReportingController(/*should_report_metrics=*/true,
+    : CompositorFrameReportingController(/*should_report_histograms=*/false,
+                                         /*should_report_ukm=*/false,
                                          /*layer_tree_host_id=*/1) {}
 
 void FakeCompositorFrameReportingController::WillBeginMainFrame(
diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h
index be6dff9c..f7cfc6fb 100644
--- a/cc/test/fake_proxy.h
+++ b/cc/test/fake_proxy.h
@@ -56,8 +56,6 @@
       base::WritableSharedMemoryMapping ukm_smoothness_data) override {}
   void SetRenderFrameObserver(
       std::unique_ptr<RenderFrameMetadataObserver> observer) override {}
-  void SetEnableFrameRateThrottling(
-      bool enable_frame_rate_throttling) override {}
   uint32_t GetAverageThroughput() const override;
 
  private:
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 730f395..e28407b 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -1921,12 +1921,6 @@
   proxy_->SetRenderFrameObserver(std::move(observer));
 }
 
-void LayerTreeHost::SetEnableFrameRateThrottling(
-    bool enable_frame_rate_throttling) {
-  DCHECK(IsMainThread());
-  proxy_->SetEnableFrameRateThrottling(enable_frame_rate_throttling);
-}
-
 void LayerTreeHost::SetDelegatedInkMetadata(
     std::unique_ptr<gfx::DelegatedInkMetadata> metadata) {
   pending_commit_state()->delegated_ink_metadata = std::move(metadata);
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index feccd6a..0995c22 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -441,10 +441,6 @@
         ->event_listener_properties[static_cast<size_t>(event_class)];
   }
 
-  // Indicates that its acceptable to throttle the frame rate for this content
-  // to prioritize lower power/CPU use.
-  void SetEnableFrameRateThrottling(bool enable_frame_rate_throttling);
-
   void SetViewportRectAndScale(
       const gfx::Rect& device_viewport_rect,
       float device_scale_factor,
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 281fca2c..a114f79 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -385,7 +385,9 @@
       current_begin_frame_tracker_(FROM_HERE),
       compositor_frame_reporting_controller_(
           std::make_unique<CompositorFrameReportingController>(
-              /*should_report_metrics=*/!settings.single_thread_proxy_scheduler,
+              /*should_report_histograms=*/!settings
+                  .single_thread_proxy_scheduler,
+              /*should_report_ukm=*/!settings.single_thread_proxy_scheduler,
               id)),
       settings_(settings),
       is_synchronous_single_threaded_(!task_runner_provider->HasImplThread() &&
@@ -1529,11 +1531,6 @@
   viewport_damage_rect_.Union(damage_rect);
 }
 
-void LayerTreeHostImpl::SetEnableFrameRateThrottling(
-    bool enable_frame_rate_throttling) {
-  enable_frame_rate_throttling_ = enable_frame_rate_throttling;
-}
-
 void LayerTreeHostImpl::InvalidateContentOnImplSide() {
   DCHECK(!pending_tree_);
   // Invalidation should never be ran outside the impl frame for non
@@ -2670,13 +2667,11 @@
   constexpr auto kTwiceOfDefaultInterval =
       viz::BeginFrameArgs::DefaultInterval() * 2;
   constexpr auto kMinDelta = kTwiceOfDefaultInterval - kFudgeDelta;
-  if (enable_frame_rate_throttling_) {
-    metadata.preferred_frame_interval = viz::BeginFrameArgs::MaxInterval();
-  } else if (mutator_host_->MainThreadAnimationsCount() == 0 &&
-             !mutator_host_->HasSmilAnimation() &&
-             mutator_host_->NeedsTickAnimations() &&
-             !frame_rate_estimator_.input_priority_mode() &&
-             mutator_host_->MinimumTickInterval() > kMinDelta) {
+  if (mutator_host_->MainThreadAnimationsCount() == 0 &&
+      !mutator_host_->HasSmilAnimation() &&
+      mutator_host_->NeedsTickAnimations() &&
+      !frame_rate_estimator_.input_priority_mode() &&
+      mutator_host_->MinimumTickInterval() > kMinDelta) {
     // All animations are impl-thread animations that tick at no more than
     // half the default display compositing fps.
     // Here and below with FrameRateEstimator::GetPreferredInterval(), the
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index a8df269..72037f3 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -344,7 +344,6 @@
   void DidAnimateScrollOffset();
   void SetFullViewportDamage();
   void SetViewportDamage(const gfx::Rect& damage_rect);
-  void SetEnableFrameRateThrottling(bool enable_frame_rate_throttling);
 
   // Interface for ThreadedInputHandler
   void BindToInputHandler(
@@ -1276,8 +1275,6 @@
   FrameRateEstimator frame_rate_estimator_;
   bool has_observed_first_scroll_delay_ = false;
 
-  bool enable_frame_rate_throttling_ = false;
-
   // True if we are measuring smoothness in TotalFrameCounter and
   // DroppedFrameCounter. Currently true when first contentful paint is done.
   bool is_measuring_smoothness_ = false;
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index ce648e1..6c879ed9 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -101,9 +101,6 @@
   virtual void SetRenderFrameObserver(
       std::unique_ptr<RenderFrameMetadataObserver> observer) = 0;
 
-  virtual void SetEnableFrameRateThrottling(
-      bool enable_frame_rate_throttling) = 0;
-
   // Returns a percentage representing average throughput of last X seconds.
   // Only implemenented for single threaded proxy.
   virtual uint32_t GetAverageThroughput() const = 0;
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
index 9bce37ac..abaa6e9 100644
--- a/cc/trees/proxy_impl.cc
+++ b/cc/trees/proxy_impl.cc
@@ -892,11 +892,6 @@
   host_impl_->SetRenderFrameObserver(std::move(observer));
 }
 
-void ProxyImpl::SetEnableFrameRateThrottling(
-    bool enable_frame_rate_throttling) {
-  host_impl_->SetEnableFrameRateThrottling(enable_frame_rate_throttling);
-}
-
 ProxyImpl::DataForCommit::DataForCommit(
     std::unique_ptr<ScopedCommitCompletionEvent> commit_completion_event,
     std::unique_ptr<CommitState> commit_state,
diff --git a/cc/trees/proxy_impl.h b/cc/trees/proxy_impl.h
index 2d545fa..251eee4 100644
--- a/cc/trees/proxy_impl.h
+++ b/cc/trees/proxy_impl.h
@@ -81,7 +81,6 @@
       base::WritableSharedMemoryMapping ukm_smoothness_data);
   void SetRenderFrameObserver(
       std::unique_ptr<RenderFrameMetadataObserver> observer);
-  void SetEnableFrameRateThrottling(bool enable_frame_rate_throttling);
 
   void MainFrameWillHappenOnImplForTesting(CompletionEvent* completion,
                                            bool* main_frame_will_happen);
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
index 0f363615..09d1639 100644
--- a/cc/trees/proxy_main.cc
+++ b/cc/trees/proxy_main.cc
@@ -760,14 +760,6 @@
                      base::Unretained(proxy_impl_.get()), std::move(observer)));
 }
 
-void ProxyMain::SetEnableFrameRateThrottling(
-    bool enable_frame_rate_throttling) {
-  ImplThreadTaskRunner()->PostTask(
-      FROM_HERE, base::BindOnce(&ProxyImpl::SetEnableFrameRateThrottling,
-                                base::Unretained(proxy_impl_.get()),
-                                enable_frame_rate_throttling));
-}
-
 uint32_t ProxyMain::GetAverageThroughput() const {
   NOTIMPLEMENTED();
   return 0u;
diff --git a/cc/trees/proxy_main.h b/cc/trees/proxy_main.h
index 79c20ca..7b6736a 100644
--- a/cc/trees/proxy_main.h
+++ b/cc/trees/proxy_main.h
@@ -117,7 +117,6 @@
       base::WritableSharedMemoryMapping ukm_smoothness_data) override;
   void SetRenderFrameObserver(
       std::unique_ptr<RenderFrameMetadataObserver> observer) override;
-  void SetEnableFrameRateThrottling(bool enable_frame_rate_throttling) override;
   uint32_t GetAverageThroughput() const override;
 
   // Returns |true| if the request was actually sent, |false| if one was
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 427392f27..3bd1669e 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -896,11 +896,6 @@
   host_impl_->SetRenderFrameObserver(std::move(observer));
 }
 
-void SingleThreadProxy::SetEnableFrameRateThrottling(
-    bool enable_frame_rate_throttling) {
-  DCHECK(task_runner_provider_->IsMainThread());
-}
-
 uint32_t SingleThreadProxy::GetAverageThroughput() const {
   DebugScopedSetImplThread impl(task_runner_provider_);
   return host_impl_->dropped_frame_counter()->GetAverageThroughput();
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index 148c0d0..1de6eea6 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -76,7 +76,6 @@
       base::WritableSharedMemoryMapping ukm_smoothness_data) override;
   void SetRenderFrameObserver(
       std::unique_ptr<RenderFrameMetadataObserver> observer) override;
-  void SetEnableFrameRateThrottling(bool enable_frame_rate_throttling) override;
   uint32_t GetAverageThroughput() const override;
 
   void UpdateBrowserControlsState(BrowserControlsState constraints,
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 18677be3..dbeedd01 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -12,8 +12,6 @@
 import("//chrome/android/chrome_java_resources.gni")
 import("//chrome/android/chrome_public_apk_tmpl.gni")
 import("//chrome/android/features/dev_ui/dev_ui_module.gni")
-import(
-    "//chrome/android/features/start_surface/public/start_surface_public_java_sources.gni")
 import("//chrome/android/features/tab_ui/buildflags.gni")
 import("//chrome/android/features/tab_ui/tab_management_java_sources.gni")
 import("//chrome/android/features/vr/public_vr_java_sources.gni")
@@ -687,7 +685,6 @@
 
   # Include sources from public_tab_management_java_sources.gni.
   sources += public_tab_management_java_sources
-  sources += start_surface_public_java_sources
 
   if (enable_arcore) {
     deps += [
@@ -939,6 +936,7 @@
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//build/config/android/test/classpath_order:junit_tests",
     "//cc:cc_java",
     "//chrome/android:update_proto_java",
@@ -1239,6 +1237,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:jni_java",
+    "//build/android:build_java",
     "//cc:cc_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/android/browserservices/intents:java",
@@ -1277,6 +1276,7 @@
     ":chrome_unit_test_util_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/ui/android/toolbar:java",
     "//chrome/test/android:chrome_java_test_support",
@@ -1317,6 +1317,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//build/config/android/test/resource_overlay:javatests",
     "//cc:cc_java",
     "//chrome/android:chrome_java",
@@ -1709,6 +1710,7 @@
     ":chrome_test_util_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/android:delegate_public_impl_java",
     "//chrome/android/features/vr:java",
@@ -2389,6 +2391,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:jni_java",
+    "//build/android:build_java",
     "//chrome/browser/download/android:java",
     "//chrome/browser/prefetch/android:java",
     "//chrome/browser/profiles/android:java",
@@ -2521,6 +2524,7 @@
     ":base_module_java",
     "//android_webview:android_webview_no_weblayer_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/version_info/android:version_constants_java",
     "//components/version_info/android:version_constants_java",
     "//content/public/android:content_java",
@@ -2585,6 +2589,7 @@
     "$google_play_services_package:google_firebase_firebase_messaging_java",
     "$google_play_services_package:google_play_services_gcm_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/download/android:file_provider_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/language/android:base_module_java",
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn
index 2eb087f8..a8e79d0 100644
--- a/chrome/android/features/autofill_assistant/BUILD.gn
+++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -39,6 +39,7 @@
     ":test_support_jni_headers",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//components/autofill_assistant/android:java",
     "//components/autofill_assistant/browser:proto_java",
     "//content/public/test/android:content_java_test_support",
@@ -113,6 +114,7 @@
     ":test_support_jni_headers",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_app_java_resources",
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_test_java",
diff --git a/chrome/android/features/cablev2_authenticator/BUILD.gn b/chrome/android/features/cablev2_authenticator/BUILD.gn
index 8465a27..90faab6 100644
--- a/chrome/android/features/cablev2_authenticator/BUILD.gn
+++ b/chrome/android/features/cablev2_authenticator/BUILD.gn
@@ -19,6 +19,7 @@
     "$google_play_services_package:google_play_services_base_java",
     "$google_play_services_package:google_play_services_tasks_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/webauthn/android:java_resources",
     "//components/webauthn/android:java",
     "//content/public/android:content_java",
diff --git a/chrome/android/features/dev_ui/BUILD.gn b/chrome/android/features/dev_ui/BUILD.gn
index 2edf36e8..672f457 100644
--- a/chrome/android/features/dev_ui/BUILD.gn
+++ b/chrome/android/features/dev_ui/BUILD.gn
@@ -16,6 +16,7 @@
 android_library("java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android/features/dev_ui/public:java",
   ]
   sources =
diff --git a/chrome/android/features/keyboard_accessory/BUILD.gn b/chrome/android/features/keyboard_accessory/BUILD.gn
index 0590ad49..153b864 100644
--- a/chrome/android/features/keyboard_accessory/BUILD.gn
+++ b/chrome/android/features/keyboard_accessory/BUILD.gn
@@ -61,6 +61,7 @@
     "public:public_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_test_java",
     "//chrome/android:chrome_test_util_java",
@@ -119,6 +120,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_test_util_java",
     "//chrome/android/features/keyboard_accessory/public:public_java",
diff --git a/chrome/android/features/keyboard_accessory/internal/BUILD.gn b/chrome/android/features/keyboard_accessory/internal/BUILD.gn
index ba5dac7..45c93e2 100644
--- a/chrome/android/features/keyboard_accessory/internal/BUILD.gn
+++ b/chrome/android/features/keyboard_accessory/internal/BUILD.gn
@@ -11,6 +11,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/favicon/android:java",
 
     # TODO(crbug/951695): Cyclic dependency. Depend on public only when ready.
diff --git a/chrome/android/features/start_surface/BUILD.gn b/chrome/android/features/start_surface/BUILD.gn
index bc6e8e4..f74844e 100644
--- a/chrome/android/features/start_surface/BUILD.gn
+++ b/chrome/android/features/start_surface/BUILD.gn
@@ -15,6 +15,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
diff --git a/chrome/android/features/start_surface/internal/BUILD.gn b/chrome/android/features/start_surface/internal/BUILD.gn
index 1b58016..98e7a972 100644
--- a/chrome/android/features/start_surface/internal/BUILD.gn
+++ b/chrome/android/features/start_surface/internal/BUILD.gn
@@ -28,14 +28,9 @@
     "java/res/drawable-xxhdpi/ic_home.png",
     "java/res/drawable-xxxhdpi/ic_explore.png",
     "java/res/drawable-xxxhdpi/ic_home.png",
-    "java/res/drawable/single_tab_background.xml",
-    "java/res/layout/query_tiles_layout.xml",
-    "java/res/layout/single_tab_view_layout.xml",
     "java/res/layout/ss_bottom_bar_layout.xml",
     "java/res/layout/ss_explore_button.xml",
     "java/res/layout/ss_home_button.xml",
-    "java/res/layout/tasks_surface_search_box_layout.xml",
-    "java/res/layout/tasks_view_layout.xml",
     "java/res/values/dimens.xml",
     "java/res/values/ids.xml",
   ]
@@ -66,16 +61,6 @@
     "java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java",
     "java/src/org/chromium/chrome/features/start_surface/StartSurfaceProperties.java",
     "java/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinder.java",
-    "java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java",
-    "java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediator.java",
-    "java/src/org/chromium/chrome/features/tasks/SingleTabView.java",
-    "java/src/org/chromium/chrome/features/tasks/SingleTabViewBinder.java",
-    "java/src/org/chromium/chrome/features/tasks/SingleTabViewProperties.java",
-    "java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java",
-    "java/src/org/chromium/chrome/features/tasks/TasksSurfaceMediator.java",
-    "java/src/org/chromium/chrome/features/tasks/TasksSurfaceProperties.java",
-    "java/src/org/chromium/chrome/features/tasks/TasksView.java",
-    "java/src/org/chromium/chrome/features/tasks/TasksViewBinder.java",
   ]
 
   deps = [
@@ -87,7 +72,6 @@
     "//chrome/browser/android/lifecycle:java",
     "//chrome/browser/browser_controls/android:java",
     "//chrome/browser/feed/android:java",
-    "//chrome/browser/feedback/android:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/lens:java",
     "//chrome/browser/preferences:java",
@@ -104,7 +88,6 @@
     "//components/browser_ui/bottomsheet/android:java",
     "//components/browser_ui/styles/android:java",
     "//components/browser_ui/widget/android:java",
-    "//components/content_settings/android:content_settings_enums_java",
     "//components/embedder_support/android:util_java",
     "//components/prefs/android:java",
     "//components/user_prefs/android:java",
@@ -113,10 +96,7 @@
     "//third_party/android_deps:material_design_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
-    "//third_party/androidx:androidx_appcompat_appcompat_resources_java",
     "//third_party/androidx:androidx_browser_browser_java",
-    "//third_party/androidx:androidx_coordinatorlayout_coordinatorlayout_java",
-    "//third_party/androidx:androidx_core_core_java",
     "//third_party/androidx:androidx_recyclerview_recyclerview_java",
     "//third_party/androidx:androidx_vectordrawable_vectordrawable_animated_java",
     "//ui/android:ui_full_java",
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
index b76850f..6d4c084 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
@@ -26,7 +26,6 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.feed.FeedSwipeRefreshLayout;
 import org.chromium.chrome.browser.feed.ScrollListener;
@@ -43,14 +42,13 @@
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
+import org.chromium.chrome.browser.tasks.TasksSurface;
+import org.chromium.chrome.browser.tasks.TasksSurfaceProperties;
 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.toolbar.top.Toolbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
-import org.chromium.chrome.features.tasks.TasksSurface;
-import org.chromium.chrome.features.tasks.TasksSurfaceCoordinator;
-import org.chromium.chrome.features.tasks.TasksSurfaceProperties;
 import org.chromium.chrome.start_surface.R;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController;
@@ -498,54 +496,6 @@
         return mTasksSurface;
     }
 
-    /**
-     * Create the {@link TasksSurface}
-     * @param activity The {@link Activity} that creates this surface.
-     * @param scrimCoordinator The {@link ScrimCoordinator} that controls scrim view.
-     * @param propertyModel The {@link PropertyModel} contains the {@link TasksSurfaceProperties}
-     *         to communicate with this surface.
-     * @param tabSwitcherType The type of the tab switcher to show.
-     * @param parentTabSupplier {@link Supplier} to provide parent tab for the
-     *         TasksSurface.
-     * @param hasMVTiles whether has MV tiles on the surface.
-     * @param windowAndroid An instance of a {@link WindowAndroid}.
-     * @param activityLifecycleDispatcher Allows observation of the activity lifecycle.
-     * @param tabModelSelector Gives access to the current set of {@TabModel}.
-     * @param snackbarManager Manages the display of snackbars.
-     * @param dynamicResourceLoaderSupplier Supplies the current {@link DynamicResourceLoader}.
-     * @param tabContentManager Gives access to the tab content.
-     * @param modalDialogManager Manages the display of modal dialogs.
-     * @param browserControlsStateProvider Gives access to the state of the browser controls.
-     * @param tabCreatorManager Manages creation of tabs.
-     * @param menuOrKeyboardActionController allows access to menu or keyboard actions.
-     * @param shareDelegateSupplier Supplies the current {@link ShareDelegate}.
-     * @param multiWindowModeStateDispatcher Gives access to the multi window mode state.
-     * @param rootView The root view of the app.
-     * @return The {@link TasksSurface}.
-     */
-    TasksSurface createTasksSurface(@NonNull Activity activity,
-            @NonNull ScrimCoordinator scrimCoordinator, @NonNull PropertyModel propertyModel,
-            @TabSwitcherType int tabSwitcherType, @NonNull Supplier<Tab> parentTabSupplier,
-            boolean hasMVTiles, boolean hasQueryTiles, @NonNull WindowAndroid windowAndroid,
-            @NonNull ActivityLifecycleDispatcher activityLifecycleDispatcher,
-            @NonNull TabModelSelector tabModelSelector, @NonNull SnackbarManager snackbarManager,
-            @NonNull Supplier<DynamicResourceLoader> dynamicResourceLoaderSupplier,
-            @NonNull TabContentManager tabContentManager,
-            @NonNull ModalDialogManager modalDialogManager,
-            @NonNull BrowserControlsStateProvider browserControlsStateProvider,
-            @NonNull TabCreatorManager tabCreatorManager,
-            @NonNull MenuOrKeyboardActionController menuOrKeyboardActionController,
-            @NonNull Supplier<ShareDelegate> shareDelegateSupplier,
-            @NonNull MultiWindowModeStateDispatcher multiWindowModeStateDispatcher,
-            @NonNull ViewGroup rootView) {
-        return new TasksSurfaceCoordinator(activity, scrimCoordinator, propertyModel,
-                tabSwitcherType, parentTabSupplier, hasMVTiles, hasQueryTiles, windowAndroid,
-                activityLifecycleDispatcher, tabModelSelector, snackbarManager,
-                dynamicResourceLoaderSupplier, tabContentManager, modalDialogManager,
-                browserControlsStateProvider, tabCreatorManager, menuOrKeyboardActionController,
-                shareDelegateSupplier, multiWindowModeStateDispatcher, rootView);
-    }
-
     @VisibleForTesting
     public boolean isInitPendingForTesting() {
         return mIsInitPending;
@@ -587,12 +537,13 @@
         if (StartSurfaceConfiguration.START_SURFACE_LAST_ACTIVE_TAB_ONLY.getValue()) {
             tabSwitcherType = TabSwitcherType.SINGLE;
         }
-        mTasksSurface = createTasksSurface(mActivity, mScrimCoordinator, mPropertyModel,
-                tabSwitcherType, mParentTabSupplier, !excludeMVTiles, !excludeQueryTiles,
-                mWindowAndroid, mActivityLifecycleDispatcher, mTabModelSelector, mSnackbarManager,
-                mDynamicResourceLoaderSupplier, mTabContentManager, mModalDialogManager,
-                mBrowserControlsManager, mTabCreatorManager, mMenuOrKeyboardActionController,
-                mShareDelegateSupplier, mMultiWindowModeStateDispatcher, mContainerView);
+        mTasksSurface = TabManagementModuleProvider.getDelegate().createTasksSurface(mActivity,
+                mScrimCoordinator, mPropertyModel, tabSwitcherType, mParentTabSupplier,
+                !excludeMVTiles, !excludeQueryTiles, mWindowAndroid, mActivityLifecycleDispatcher,
+                mTabModelSelector, mSnackbarManager, mDynamicResourceLoaderSupplier,
+                mTabContentManager, mModalDialogManager, mBrowserControlsManager,
+                mTabCreatorManager, mMenuOrKeyboardActionController, mShareDelegateSupplier,
+                mMultiWindowModeStateDispatcher, mContainerView);
         mTasksSurface.getView().setId(R.id.primary_tasks_surface_view);
         initializeOffsetChangedListener();
         addHeaderOffsetChangeListener(mOffsetChangedListenerToGenerateScrollEvents);
@@ -609,8 +560,9 @@
 
         PropertyModel propertyModel = new PropertyModel(TasksSurfaceProperties.ALL_KEYS);
         mStartSurfaceMediator.setSecondaryTasksSurfacePropertyModel(propertyModel);
-        mSecondaryTasksSurface = createTasksSurface(mActivity, mScrimCoordinator, propertyModel,
-                TabSwitcherType.GRID, mParentTabSupplier,
+        mSecondaryTasksSurface = TabManagementModuleProvider.getDelegate().createTasksSurface(
+                mActivity, mScrimCoordinator, propertyModel, TabSwitcherType.GRID,
+                mParentTabSupplier,
                 /* hasMVTiles= */ false, /* hasQueryTiles= */ false, mWindowAndroid,
                 mActivityLifecycleDispatcher, mTabModelSelector, mSnackbarManager,
                 mDynamicResourceLoaderSupplier, mTabContentManager, mModalDialogManager,
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
index 828e117..4211627 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
@@ -44,11 +44,11 @@
 import org.chromium.chrome.browser.tab.TabUtils;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
+import org.chromium.chrome.browser.tasks.TasksSurface;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher.TabListDelegate;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities;
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
-import org.chromium.chrome.features.tasks.TasksSurface;
 import org.chromium.components.browser_ui.widget.animation.Interpolators;
 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
 import org.chromium.components.browser_ui.widget.scrim.ScrimProperties;
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
index 7997ee7..def392d 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -4,6 +4,23 @@
 
 package org.chromium.chrome.features.start_surface;
 
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_INITIALIZED;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_LENS_BUTTON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_SURFACE_BODY_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MORE_TABS_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MV_TILES_CONTAINER_TOP_MARGIN;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MV_TILES_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.QUERY_TILES_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.RESET_TASK_SURFACE_HEADER_SCROLL_POSITION;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.TAB_SWITCHER_TITLE_TOP_MARGIN;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.TASKS_SURFACE_BODY_TOP_MARGIN;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.TOP_TOOLBAR_PLACEHOLDER_HEIGHT;
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.BOTTOM_BAR_HEIGHT;
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.EXPLORE_SURFACE_COORDINATOR;
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_EXPLORE_SURFACE_VISIBLE;
@@ -11,23 +28,6 @@
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_SHOWING_OVERVIEW;
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.RESET_FEED_SURFACE_SCROLL_POSITION;
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_INITIALIZED;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_LENS_BUTTON_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_SURFACE_BODY_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.MORE_TABS_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.MV_TILES_CONTAINER_TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.MV_TILES_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.QUERY_TILES_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.RESET_TASK_SURFACE_HEADER_SCROLL_POSITION;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TAB_SWITCHER_TITLE_TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TASKS_SURFACE_BODY_TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TOP_TOOLBAR_PLACEHOLDER_HEIGHT;
 
 import android.content.Context;
 import android.content.res.Resources;
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceBackButtonTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceBackButtonTest.java
index 3fc39f1..58d231c3 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceBackButtonTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceBackButtonTest.java
@@ -65,7 +65,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorTestingRobot;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper;
-import org.chromium.chrome.start_surface.R;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeApplicationTestUtils;
@@ -187,7 +186,7 @@
         // surface.
         StartSurfaceTestUtils.launchFirstMVTile(cta, /* currentTabCount = */ 1);
         StartSurfaceTestUtils.pressHomePageButton(cta);
-        onViewWaiting(withId(R.id.primary_tasks_surface_view));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.primary_tasks_surface_view));
         onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view), isDisplayed()));
 
         // Launches the new tab from the carousel tab switcher, and press back button.
@@ -196,7 +195,7 @@
                 cta.getTabModelSelector().getCurrentTab().getLaunchType());
         CriteriaHelper.pollUiThread(() -> !cta.getLayoutManager().overviewVisible());
         StartSurfaceTestUtils.pressBack(mActivityTestRule);
-        onViewWaiting(withId(R.id.primary_tasks_surface_view));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.primary_tasks_surface_view));
         // Verifies the tab isn't auto deleted from the TabModel.
         TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
     }
@@ -250,9 +249,9 @@
         // Enters the tab switcher, and choose the new tab. After the tab is opening, press back.
         waitForView(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_button));
         TabUiTestHelper.enterTabSwitcher(cta);
-        waitForView(withId(R.id.secondary_tasks_surface_view));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.secondary_tasks_surface_view));
         waitForView(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view));
-        onView(allOf(withParent(withId(R.id.tasks_surface_body)),
+        onView(allOf(withParent(withId(org.chromium.chrome.tab_ui.R.id.tasks_surface_body)),
                        withId(org.chromium.chrome.tab_ui.R.id.tab_list_view)))
                 .perform(RecyclerViewActions.actionOnItemAtPosition(1, click()));
         CriteriaHelper.pollUiThread(() -> !cta.getLayoutManager().overviewVisible());
@@ -305,8 +304,10 @@
         StartSurfaceTestUtils.waitForTabModel(cta);
         TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
 
-        onViewWaiting(withId(R.id.search_box_text)).perform(replaceText("about:blank"));
-        onView(withId(R.id.url_bar)).perform(pressKey(KeyEvent.KEYCODE_ENTER));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.search_box_text))
+                .perform(replaceText("about:blank"));
+        onView(withId(org.chromium.chrome.start_surface.R.id.url_bar))
+                .perform(pressKey(KeyEvent.KEYCODE_ENTER));
         LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
         TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
 
@@ -320,7 +321,8 @@
 
         StartSurfaceTestUtils.pressBack(mActivityTestRule);
         waitForView(withId(org.chromium.chrome.tab_ui.R.id.dialog_container_view), VIEW_GONE);
-        onView(withId(R.id.primary_tasks_surface_view)).check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.start_surface.R.id.primary_tasks_surface_view))
+                .check(matches(isDisplayed()));
     }
 
     @Test
@@ -350,7 +352,7 @@
         StartSurfaceTestUtils.waitForOverviewVisible(
                 mLayoutChangedCallbackHelper, mCurrentlyActiveLayout);
         StartSurfaceTestUtils.waitForTabModel(cta);
-        onViewWaiting(withId(R.id.logo));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.logo));
 
         // Launches the first site in mv tiles.
         StartSurfaceTestUtils.launchFirstMVTile(cta, /* currentTabCount = */ 1);
@@ -366,7 +368,7 @@
         onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_button));
         TabUiTestHelper.enterTabSwitcher(cta);
 
-        waitForView(withId(R.id.secondary_tasks_surface_view));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.secondary_tasks_surface_view));
         StartSurfaceCoordinator startSurfaceCoordinator =
                 StartSurfaceTestUtils.getStartSurfaceFromUIThread(cta);
         TestThreadUtils.runOnUiThreadBlocking(
@@ -384,7 +386,7 @@
         // Verifies that tapping the back button will close the TabSelectionEditor.
         StartSurfaceTestUtils.pressBack(mActivityTestRule);
         robot.resultRobot.verifyTabSelectionEditorIsHidden();
-        onViewWaiting(withId(R.id.secondary_tasks_surface_view));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.secondary_tasks_surface_view));
 
         // Groups the two tabs.
         TestThreadUtils.runOnUiThreadBlocking(
@@ -397,7 +399,8 @@
         robot.resultRobot.verifyTabSelectionEditorIsHidden();
 
         // Opens the TabGridDialog by clicking the first group card.
-        onViewWaiting(Matchers.allOf(withParent(withId(R.id.tasks_surface_body)),
+        onViewWaiting(Matchers.allOf(withParent(withId(
+                                             org.chromium.chrome.tab_ui.R.id.tasks_surface_body)),
                               withId(org.chromium.chrome.tab_ui.R.id.tab_list_view)))
                 .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
         CriteriaHelper.pollUiThread(() -> isTabGridDialogShown(cta));
@@ -405,7 +408,7 @@
         // Verifies that the TabGridDialog is closed by tapping back button.
         StartSurfaceTestUtils.pressBack(mActivityTestRule);
         CriteriaHelper.pollUiThread(() -> isTabGridDialogHidden(cta));
-        onViewWaiting(withId(R.id.secondary_tasks_surface_view));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.secondary_tasks_surface_view));
     }
 
     @Test
@@ -435,7 +438,7 @@
         StartSurfaceTestUtils.waitForOverviewVisible(
                 mLayoutChangedCallbackHelper, mCurrentlyActiveLayout);
         StartSurfaceTestUtils.waitForTabModel(cta);
-        onViewWaiting(withId(R.id.logo));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.logo));
 
         // Launches the first site in MV tiles to create the second tab for grouping.
         StartSurfaceTestUtils.launchFirstMVTile(cta, /* currentTabCount = */ 1);
@@ -449,13 +452,13 @@
             return;
         }
         TabUiTestHelper.enterTabSwitcher(cta);
-        waitForView(withId(R.id.secondary_tasks_surface_view));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.secondary_tasks_surface_view));
         List<Tab> tabs = getTabsInCurrentTabModel(cta.getCurrentTabModel());
         TabSelectionEditorTestingRobot robot = new TabSelectionEditorTestingRobot();
 
         // Enters the homepage, and shows the TabSelectionEditor dialog.
         StartSurfaceTestUtils.pressHomePageButton(cta);
-        waitForView(withId(R.id.primary_tasks_surface_view));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.primary_tasks_surface_view));
 
         StartSurfaceCoordinator startSurfaceCoordinator =
                 StartSurfaceTestUtils.getStartSurfaceFromUIThread(cta);
@@ -474,7 +477,7 @@
         // Verifies that tapping the back button will close the TabSelectionEditor.
         StartSurfaceTestUtils.pressBack(mActivityTestRule);
         robot.resultRobot.verifyTabSelectionEditorIsHidden();
-        onViewWaiting(withId(R.id.primary_tasks_surface_view));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.primary_tasks_surface_view));
     }
 
     @Test
@@ -565,7 +568,7 @@
         StartSurfaceTestUtils.waitForOverviewVisible(
                 mLayoutChangedCallbackHelper, mCurrentlyActiveLayout);
         StartSurfaceTestUtils.waitForTabModel(cta);
-        onViewWaiting(withId(R.id.logo));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.logo));
 
         // Open an incognito tab from Start.
         MostVisitedTilesCarouselLayout mvTilesLayout = mActivityTestRule.getActivity().findViewById(
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceFinaleTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceFinaleTest.java
index d17edb2..26bd8c7 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceFinaleTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceFinaleTest.java
@@ -59,7 +59,6 @@
 import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper;
 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
-import org.chromium.chrome.start_surface.R;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
@@ -159,16 +158,18 @@
         // Launches a new Tab from the Start surface, and verifies the omnibox is focused.
         TestThreadUtils.runOnUiThreadBlocking(() -> cta.getTabCreator(false).launchNTP());
         TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
-        waitForView(withId(R.id.search_box_text));
-        TextView urlBar = cta.findViewById(R.id.url_bar);
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.search_box_text));
+        TextView urlBar = cta.findViewById(org.chromium.chrome.start_surface.R.id.url_bar);
         CriteriaHelper.pollUiThread(
                 ()
                         -> StartSurfaceTestUtils.isKeyboardShown(mActivityTestRule)
                         && urlBar.isFocused(),
                 MAX_TIMEOUT_MS, CriteriaHelper.DEFAULT_POLLING_INTERVAL);
-        waitForView(withId(R.id.voice_search_button));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.voice_search_button));
         Assert.assertTrue(TextUtils.isEmpty(urlBar.getText()));
-        assertEquals(cta.findViewById(R.id.toolbar_buttons).getVisibility(), View.INVISIBLE);
+        assertEquals(cta.findViewById(org.chromium.chrome.start_surface.R.id.toolbar_buttons)
+                             .getVisibility(),
+                View.INVISIBLE);
         ToolbarDataProvider toolbarDataProvider =
                 cta.getToolbarManager().getLocationBarModelForTesting();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
@@ -177,18 +178,19 @@
 
         // Navigates the new created Tab.
         TestThreadUtils.runOnUiThreadBlocking(() -> urlBar.setText("about:blank"));
-        onView(withId(R.id.url_bar)).perform(pressKey(KeyEvent.KEYCODE_ENTER));
+        onView(withId(org.chromium.chrome.start_surface.R.id.url_bar))
+                .perform(pressKey(KeyEvent.KEYCODE_ENTER));
 
         // Launches a new Tab from the newly navigated tab, and verifies the omnibox is focused.
         TestThreadUtils.runOnUiThreadBlocking(() -> cta.getTabCreator(false).launchNTP());
         TabUiTestHelper.verifyTabModelTabCount(cta, 3, 0);
-        waitForView(withId(R.id.search_box_text));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.search_box_text));
         CriteriaHelper.pollUiThread(
                 ()
                         -> StartSurfaceTestUtils.isKeyboardShown(mActivityTestRule)
                         && urlBar.isFocused(),
                 MAX_TIMEOUT_MS, CriteriaHelper.DEFAULT_POLLING_INTERVAL);
-        waitForView(withId(R.id.voice_search_button));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.voice_search_button));
         Assert.assertTrue(TextUtils.isEmpty(urlBar.getText()));
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             assertTrue(TextUtils.equals(toolbarDataProvider.getCurrentUrl(), UrlConstants.NTP_URL));
@@ -215,16 +217,18 @@
         // Launches a new Tab from the Start surface, and verifies the omnibox is focused.
         TestThreadUtils.runOnUiThreadBlocking(() -> cta.getTabCreator(false).launchNTP());
         TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
-        waitForView(withId(R.id.search_box_text));
-        TextView urlBar = cta.findViewById(R.id.url_bar);
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.search_box_text));
+        TextView urlBar = cta.findViewById(org.chromium.chrome.start_surface.R.id.url_bar);
         CriteriaHelper.pollUiThread(
                 ()
                         -> StartSurfaceTestUtils.isKeyboardShown(mActivityTestRule)
                         && urlBar.isFocused(),
                 MAX_TIMEOUT_MS, CriteriaHelper.DEFAULT_POLLING_INTERVAL);
-        waitForView(withId(R.id.voice_search_button));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.voice_search_button));
         Assert.assertTrue(TextUtils.isEmpty(urlBar.getText()));
-        assertEquals(cta.findViewById(R.id.toolbar_buttons).getVisibility(), View.INVISIBLE);
+        assertEquals(cta.findViewById(org.chromium.chrome.start_surface.R.id.toolbar_buttons)
+                             .getVisibility(),
+                View.INVISIBLE);
         ToolbarDataProvider toolbarDataProvider =
                 cta.getToolbarManager().getLocationBarModelForTesting();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
@@ -233,18 +237,19 @@
 
         // Navigates the new created Tab.
         TestThreadUtils.runOnUiThreadBlocking(() -> urlBar.setText("about:blank"));
-        onView(withId(R.id.url_bar)).perform(pressKey(KeyEvent.KEYCODE_ENTER));
+        onView(withId(org.chromium.chrome.start_surface.R.id.url_bar))
+                .perform(pressKey(KeyEvent.KEYCODE_ENTER));
 
         // Launches a new Tab from the newly navigated tab, and verifies the omnibox is focused.
         TestThreadUtils.runOnUiThreadBlocking(() -> cta.getTabCreator(false).launchNTP());
         TabUiTestHelper.verifyTabModelTabCount(cta, 3, 0);
-        waitForView(withId(R.id.search_box_text));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.search_box_text));
         CriteriaHelper.pollUiThread(
                 ()
                         -> StartSurfaceTestUtils.isKeyboardShown(mActivityTestRule)
                         && urlBar.isFocused(),
                 MAX_TIMEOUT_MS, CriteriaHelper.DEFAULT_POLLING_INTERVAL);
-        waitForView(withId(R.id.voice_search_button));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.voice_search_button));
         Assert.assertTrue(TextUtils.isEmpty(urlBar.getText()));
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             assertTrue(TextUtils.equals(toolbarDataProvider.getCurrentUrl(), UrlConstants.NTP_URL));
@@ -265,15 +270,18 @@
         StartSurfaceTestUtils.waitForTabModel(cta);
         TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
 
-        onViewWaiting(allOf(withId(R.id.search_box_text), isDisplayed()))
+        onViewWaiting(allOf(withId(org.chromium.chrome.start_surface.R.id.search_box_text),
+                              isDisplayed()))
                 .perform(replaceText("about:blank"));
-        onViewWaiting(withId(R.id.url_bar)).perform(pressKey(KeyEvent.KEYCODE_ENTER));
-        waitForView(withId(R.id.primary_tasks_surface_view), ViewUtils.VIEW_INVISIBLE);
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.url_bar))
+                .perform(pressKey(KeyEvent.KEYCODE_ENTER));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.primary_tasks_surface_view),
+                ViewUtils.VIEW_INVISIBLE);
 
         TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
-        waitForView(withId(R.id.search_box_text));
-        waitForView(withId(R.id.toolbar_buttons));
-        TextView urlBar = cta.findViewById(R.id.url_bar);
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.search_box_text));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.toolbar_buttons));
+        TextView urlBar = cta.findViewById(org.chromium.chrome.start_surface.R.id.url_bar);
         Assert.assertFalse(urlBar.isFocused());
     }
 
@@ -309,9 +317,10 @@
             StartSurfaceTestUtils.waitForOverviewVisible(
                     mLayoutChangedCallbackHelper, mCurrentlyActiveLayout);
 
-            onViewWaiting(allOf(withId(R.id.mv_tiles_layout), isDisplayed()));
-            onViewWaiting(withId(R.id.carousel_tab_switcher_container));
-            onViewWaiting(withId(R.id.start_tab_switcher_button));
+            onViewWaiting(
+                    allOf(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_layout), isDisplayed()));
+            onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container));
+            onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.start_tab_switcher_button));
 
             // Launch a tab. The home button should show on the normal tab.
             StartSurfaceTestUtils.launchFirstMVTile(cta, /* currentTabCount = */ 1);
@@ -322,9 +331,10 @@
 
         // MV tiles and carousel tab switcher should not show anymore.
         StartSurfaceTestUtils.waitForOverviewVisible(cta);
-        onViewWaiting(withId(R.id.start_tab_switcher_button));
-        onView(withId(R.id.mv_tiles_container)).check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.carousel_tab_switcher_container))
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.start_tab_switcher_button));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container))
+                .check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container))
                 .check(matches(withEffectiveVisibility(GONE)));
     }
 
@@ -342,13 +352,14 @@
             StartSurfaceTestUtils.waitForOverviewVisible(
                     mLayoutChangedCallbackHelper, mCurrentlyActiveLayout);
 
-            onViewWaiting(withId(R.id.mv_tiles_layout));
-            onViewWaiting(withId(R.id.carousel_tab_switcher_container));
-            onViewWaiting(withId(R.id.start_tab_switcher_button));
+            onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_layout));
+            onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container));
+            onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.start_tab_switcher_button));
 
             // Launch a tab. The home button should show on the normal tab.
             StartSurfaceTestUtils.launchFirstMVTile(cta, /* currentTabCount = */ 1);
-            onViewWaiting(withId(R.id.home_button)).check(matches(isDisplayed()));
+            onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.home_button))
+                    .check(matches(isDisplayed()));
         }
 
         // Go back to the home surface, MV tiles and carousel tab switcher should not show anymore.
@@ -356,9 +367,10 @@
 
         // MV tiles should shown and carousel tab switcher should not show anymore.
         StartSurfaceTestUtils.waitForOverviewVisible(cta);
-        onViewWaiting(withId(R.id.start_tab_switcher_button));
-        onView(withId(R.id.mv_tiles_layout)).check(matches(withEffectiveVisibility(VISIBLE)));
-        onView(withId(R.id.carousel_tab_switcher_container))
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.start_tab_switcher_button));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_layout))
+                .check(matches(withEffectiveVisibility(VISIBLE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container))
                 .check(matches(withEffectiveVisibility(GONE)));
     }
 
@@ -383,8 +395,8 @@
                                 TabLaunchType.FROM_CHROME_UI));
         TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
         StartSurfaceTestUtils.waitForOverviewVisible(cta);
-        waitForView(withId(R.id.search_box_text));
-        TextView urlBar = cta.findViewById(R.id.url_bar);
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.search_box_text));
+        TextView urlBar = cta.findViewById(org.chromium.chrome.start_surface.R.id.url_bar);
         CriteriaHelper.pollUiThread(
                 ()
                         -> !StartSurfaceTestUtils.isKeyboardShown(mActivityTestRule)
@@ -414,16 +426,18 @@
         // Launches a new Tab from the Start surface, and verifies the omnibox is focused.
         TestThreadUtils.runOnUiThreadBlocking(() -> cta.getTabCreator(false).launchNTP());
         TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0);
-        waitForView(withId(R.id.search_box_text));
-        TextView urlBar = cta.findViewById(R.id.url_bar);
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.search_box_text));
+        TextView urlBar = cta.findViewById(org.chromium.chrome.start_surface.R.id.url_bar);
         CriteriaHelper.pollUiThread(
                 ()
                         -> StartSurfaceTestUtils.isKeyboardShown(mActivityTestRule)
                         && urlBar.isFocused(),
                 MAX_TIMEOUT_MS, CriteriaHelper.DEFAULT_POLLING_INTERVAL);
-        waitForView(withId(R.id.voice_search_button));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.voice_search_button));
         Assert.assertTrue(TextUtils.isEmpty(urlBar.getText()));
-        assertEquals(cta.findViewById(R.id.toolbar_buttons).getVisibility(), View.INVISIBLE);
+        assertEquals(cta.findViewById(org.chromium.chrome.start_surface.R.id.toolbar_buttons)
+                             .getVisibility(),
+                View.INVISIBLE);
         ToolbarDataProvider toolbarDataProvider =
                 cta.getToolbarManager().getLocationBarModelForTesting();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
@@ -432,7 +446,7 @@
 
         backAction.run();
 
-        waitForView(withId(R.id.primary_tasks_surface_view));
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.primary_tasks_surface_view));
         TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
     }
 }
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceNoTabsTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceNoTabsTest.java
index d91d418..c398894c 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceNoTabsTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceNoTabsTest.java
@@ -132,12 +132,16 @@
 
         onView(withId(R.id.primary_tasks_surface_view)).check(matches(isDisplayed()));
         onView(withId(R.id.search_box_text)).check(matches(isDisplayed()));
-        onView(withId(R.id.mv_tiles_container)).check(matches(isDisplayed()));
-        onView(withId(R.id.tab_switcher_title)).check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.carousel_tab_switcher_container))
+        onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container))
+                .check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_title))
                 .check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.more_tabs)).check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.tasks_surface_body)).check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container))
+                .check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.more_tabs))
+                .check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tasks_surface_body))
+                .check(matches(isDisplayed()));
         onView(withId(R.id.start_tab_switcher_button)).check(matches(isDisplayed()));
         onViewWaiting(withId(R.id.logo)).check(matches(isDisplayed()));
 
@@ -164,13 +168,18 @@
 
         onView(withId(R.id.primary_tasks_surface_view)).check(matches(isDisplayed()));
         onView(withId(R.id.search_box_text)).check(matches(isDisplayed()));
-        onView(withId(R.id.mv_tiles_container)).check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.tab_switcher_title)).check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.carousel_tab_switcher_container))
+        onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container))
                 .check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.single_tab_view)).check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.more_tabs)).check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.tasks_surface_body)).check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_title))
+                .check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container))
+                .check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.single_tab_view))
+                .check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.more_tabs))
+                .check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tasks_surface_body))
+                .check(matches(isDisplayed()));
     }
 
     private void pressBack() {
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTabSwitcherTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTabSwitcherTest.java
index 261c080..7bf3f97 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTabSwitcherTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTabSwitcherTest.java
@@ -63,7 +63,6 @@
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper;
 import org.chromium.chrome.browser.toolbar.HomeButton;
-import org.chromium.chrome.start_surface.R;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
@@ -163,10 +162,10 @@
             TabUiTestHelper.enterTabSwitcher(mActivityTestRule.getActivity());
         }
 
-        onViewWaiting(withId(R.id.secondary_tasks_surface_view));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.secondary_tasks_surface_view));
 
-        onViewWaiting(
-                allOf(withParent(withId(R.id.tasks_surface_body)), withId(R.id.tab_list_view)))
+        onViewWaiting(allOf(withParent(withId(org.chromium.chrome.tab_ui.R.id.tasks_surface_body)),
+                              withId(org.chromium.chrome.tab_ui.R.id.tab_list_view)))
                 .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
         LayoutTestUtils.waitForLayout(
                 mActivityTestRule.getActivity().getLayoutManager(), LayoutType.BROWSING);
@@ -186,12 +185,16 @@
                 mLayoutChangedCallbackHelper, mCurrentlyActiveLayout);
         StartSurfaceTestUtils.waitForTabModel(cta);
         TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
-        assertEquals(cta.findViewById(R.id.tab_switcher_title).getVisibility(), View.VISIBLE);
+        assertEquals(cta.findViewById(org.chromium.chrome.tab_ui.R.id.tab_switcher_title)
+                             .getVisibility(),
+                View.VISIBLE);
 
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> { cta.getTabModelSelector().getModel(false).closeAllTabs(); });
         TabUiTestHelper.verifyTabModelTabCount(cta, 0, 0);
-        assertEquals(cta.findViewById(R.id.tab_switcher_title).getVisibility(), View.GONE);
+        assertEquals(cta.findViewById(org.chromium.chrome.tab_ui.R.id.tab_switcher_title)
+                             .getVisibility(),
+                View.GONE);
     }
 
     @Test
@@ -220,42 +223,50 @@
         if (mImmediateReturn) {
             StartSurfaceTestUtils.clickFirstTabInCarousel();
         } else {
-            onViewWaiting(allOf(withId(R.id.toolbar_left_button),
-                                  isDescendantOfA(withId(R.id.bottom_controls))))
+            onViewWaiting(allOf(withId(org.chromium.chrome.tab_ui.R.id.toolbar_left_button),
+                                  isDescendantOfA(withId(
+                                          org.chromium.chrome.start_surface.R.id.bottom_controls))))
                     .perform(click());
         }
         onViewWaiting(
-                allOf(withId(R.id.tab_list_view), withParent(withId(R.id.dialog_container_view))))
+                allOf(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view),
+                        withParent(withId(org.chromium.chrome.tab_ui.R.id.dialog_container_view))))
                 .check(TabUiTestHelper.ChildrenCountAssertion.havingTabCount(2));
 
         // Show start surface through tab grid dialog toolbar plus button and create a new tab by
         // clicking on MV tiles.
-        onView(allOf(withId(R.id.toolbar_right_button),
-                       isDescendantOfA(withId(R.id.dialog_container_view))))
+        onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.toolbar_right_button),
+                       isDescendantOfA(
+                               withId(org.chromium.chrome.tab_ui.R.id.dialog_container_view))))
                 .perform(click());
         StartSurfaceTestUtils.launchFirstMVTile(cta, /* currentTabCount = */ 2);
 
         // Verify a tab is created within the group by checking the tab strip and tab model.
-        onView(withId(R.id.toolbar_container_view))
-                .check(waitForView(allOf(withId(R.id.tab_list_view), isCompletelyDisplayed())));
-        onView(allOf(withId(R.id.tab_list_view), withParent(withId(R.id.toolbar_container_view))))
+        onView(withId(org.chromium.chrome.tab_ui.R.id.toolbar_container_view))
+                .check(waitForView(allOf(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view),
+                        isCompletelyDisplayed())));
+        onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view),
+                       withParent(withId(org.chromium.chrome.tab_ui.R.id.toolbar_container_view))))
                 .check(TabUiTestHelper.ChildrenCountAssertion.havingTabCount(3));
         assertEquals(1, filter.getTabGroupCount());
 
         // Show start surface through tab strip plus button and create a new tab by perform a query
         // search in fake box.
-        onView(allOf(withId(R.id.toolbar_right_button),
-                       isDescendantOfA(withId(R.id.bottom_controls))))
+        onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.toolbar_right_button),
+                       isDescendantOfA(withId(org.chromium.chrome.tab_ui.R.id.bottom_controls))))
                 .perform(click());
-        onViewWaiting(withId(R.id.search_box_text))
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.search_box_text))
                 .check(matches(isCompletelyDisplayed()))
                 .perform(replaceText("wfh tips"));
-        onView(withId(R.id.url_bar)).perform(pressKey(KeyEvent.KEYCODE_ENTER));
+        onView(withId(org.chromium.chrome.start_surface.R.id.url_bar))
+                .perform(pressKey(KeyEvent.KEYCODE_ENTER));
 
         // Verify a tab is created within the group by checking the tab strip and tab model.
-        onView(withId(R.id.toolbar_container_view))
-                .check(waitForView(allOf(withId(R.id.tab_list_view), isCompletelyDisplayed())));
-        onView(allOf(withId(R.id.tab_list_view), withParent(withId(R.id.toolbar_container_view))))
+        onView(withId(org.chromium.chrome.tab_ui.R.id.toolbar_container_view))
+                .check(waitForView(allOf(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view),
+                        isCompletelyDisplayed())));
+        onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view),
+                       withParent(withId(org.chromium.chrome.tab_ui.R.id.toolbar_container_view))))
                 .check(TabUiTestHelper.ChildrenCountAssertion.havingTabCount(4));
         assertEquals(4, cta.getTabModelSelector().getCurrentModel().getCount());
         assertEquals(1, filter.getTabGroupCount());
@@ -279,13 +290,17 @@
         TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0);
 
         StartSurfaceTestUtils.clickMoreTabs(cta);
-        waitForView(withId(R.id.secondary_tasks_surface_view));
-        onView(withId(R.id.home_button_on_tab_switcher)).check(matches(isDisplayed()));
-        HomeButton homeButton = cta.findViewById(R.id.home_button_on_tab_switcher);
+        waitForView(withId(org.chromium.chrome.start_surface.R.id.secondary_tasks_surface_view));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.home_button_on_tab_switcher))
+                .check(matches(isDisplayed()));
+        HomeButton homeButton =
+                cta.findViewById(org.chromium.chrome.tab_ui.R.id.home_button_on_tab_switcher);
         Assert.assertFalse(homeButton.isLongClickable());
-        onView(withId(R.id.home_button_on_tab_switcher)).perform(click());
+        onView(withId(org.chromium.chrome.start_surface.R.id.home_button_on_tab_switcher))
+                .perform(click());
 
-        onView(withId(R.id.primary_tasks_surface_view)).check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.start_surface.R.id.primary_tasks_surface_view))
+                .check(matches(isDisplayed()));
     }
 
     @Test
@@ -302,7 +317,7 @@
         CriteriaHelper.pollUiThread(
                 () -> cta.getLayoutManager() != null && cta.getLayoutManager().overviewVisible());
         StartSurfaceTestUtils.waitForTabModel(cta);
-        onViewWaiting(withId(R.id.logo));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.logo));
         Tab tab1 = cta.getCurrentTabModel().getTabAt(0);
 
         // Launches the first site in MV tiles.
@@ -315,21 +330,24 @@
         // Returns to the Start surface.
         StartSurfaceTestUtils.pressHomePageButton(cta);
         LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.TAB_SWITCHER);
-        waitForView(allOf(withParent(withId(R.id.carousel_tab_switcher_container)),
-                withId(R.id.tab_list_view)));
+        waitForView(allOf(
+                withParent(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container)),
+                withId(org.chromium.chrome.tab_ui.R.id.tab_list_view)));
 
-        RecyclerView recyclerView = cta.findViewById(R.id.tab_list_view);
+        RecyclerView recyclerView = cta.findViewById(org.chromium.chrome.tab_ui.R.id.tab_list_view);
         CriteriaHelper.pollUiThread(() -> 2 == recyclerView.getChildCount());
         // Verifies that the tabs are shown in MRU order: the first card in the carousel Tab
         // switcher is the last created Tab by tapping the MV tile; the second card is the Tab
         // created or restored in setup().
         RecyclerView.ViewHolder firstViewHolder = recyclerView.findViewHolderForAdapterPosition(0);
-        TextView title1 = firstViewHolder.itemView.findViewById(R.id.tab_title);
+        TextView title1 =
+                firstViewHolder.itemView.findViewById(org.chromium.chrome.tab_ui.R.id.tab_title);
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> Assert.assertEquals(tab2.getTitle(), title1.getText()));
 
         RecyclerView.ViewHolder secondViewHolder = recyclerView.findViewHolderForAdapterPosition(1);
-        TextView title2 = secondViewHolder.itemView.findViewById(R.id.tab_title);
+        TextView title2 =
+                secondViewHolder.itemView.findViewById(org.chromium.chrome.tab_ui.R.id.tab_title);
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> Assert.assertEquals(tab1.getTitle(), title2.getText()));
     }
@@ -364,7 +382,7 @@
         CriteriaHelper.pollUiThread(() -> cta.getLayoutManager() != null);
         LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.TAB_SWITCHER);
         StartSurfaceTestUtils.waitForTabModel(cta);
-        onViewWaiting(withId(R.id.logo));
+        onViewWaiting(withId(org.chromium.chrome.start_surface.R.id.logo));
         Tab tab1 = cta.getCurrentTabModel().getTabAt(0);
 
         // Launches the first site in MV tiles.
@@ -382,22 +400,28 @@
         }
         // Enter the Tab switcher.
         TabUiTestHelper.enterTabSwitcher(cta);
-        waitForView(allOf(
-                withParent(withId(R.id.secondary_tasks_surface_view)), withId(R.id.tab_list_view)));
+        waitForView(
+                allOf(withParent(withId(
+                              org.chromium.chrome.start_surface.R.id.secondary_tasks_surface_view)),
+                        withId(org.chromium.chrome.tab_ui.R.id.tab_list_view)));
 
-        ViewGroup secondaryTaskSurface = cta.findViewById(R.id.secondary_tasks_surface_view);
-        RecyclerView recyclerView = secondaryTaskSurface.findViewById(R.id.tab_list_view);
+        ViewGroup secondaryTaskSurface = cta.findViewById(
+                org.chromium.chrome.start_surface.R.id.secondary_tasks_surface_view);
+        RecyclerView recyclerView =
+                secondaryTaskSurface.findViewById(org.chromium.chrome.tab_ui.R.id.tab_list_view);
         CriteriaHelper.pollUiThread(() -> 2 == recyclerView.getChildCount());
         // Verifies that the tabs are shown in MRU order: the first card in the Tab switcher is the
         // last created Tab by tapping the MV tile; the second card is the Tab created or restored
         // in setup().
         RecyclerView.ViewHolder firstViewHolder = recyclerView.findViewHolderForAdapterPosition(0);
-        TextView title1 = firstViewHolder.itemView.findViewById(R.id.tab_title);
+        TextView title1 =
+                firstViewHolder.itemView.findViewById(org.chromium.chrome.tab_ui.R.id.tab_title);
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> Assert.assertEquals(tab1.getTitle(), title1.getText()));
 
         RecyclerView.ViewHolder secondViewHolder = recyclerView.findViewHolderForAdapterPosition(1);
-        TextView title2 = secondViewHolder.itemView.findViewById(R.id.tab_title);
+        TextView title2 =
+                secondViewHolder.itemView.findViewById(org.chromium.chrome.tab_ui.R.id.tab_title);
         TestThreadUtils.runOnUiThreadBlocking(
                 () -> Assert.assertEquals(tab2.getTitle(), title2.getText()));
     }
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
index 39248c3..b75f3b9 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -87,10 +87,10 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
+import org.chromium.chrome.browser.tasks.SingleTabSwitcherMediator;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuTestSupport;
-import org.chromium.chrome.features.tasks.SingleTabSwitcherMediator;
 import org.chromium.chrome.start_surface.R;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
@@ -205,15 +205,19 @@
 
         onViewWaiting(withId(R.id.primary_tasks_surface_view));
         onViewWaiting(withId(R.id.search_box_text)).check(matches(isDisplayed()));
-        onView(withId(R.id.mv_tiles_container)).check(matches(isDisplayed()));
-        onView(withId(R.id.tab_switcher_title)).check(matches(isDisplayed()));
-        onView(withId(R.id.carousel_tab_switcher_container)).check(matches(isDisplayed()));
-        onView(withId(R.id.tasks_surface_body)).check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container))
+                .check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_title))
+                .check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container))
+                .check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tasks_surface_body))
+                .check(matches(isDisplayed()));
 
         StartSurfaceTestUtils.clickMoreTabs(cta);
         onViewWaiting(withId(R.id.secondary_tasks_surface_view));
-        waitForView(allOf(
-                withParent(withId(R.id.secondary_tasks_surface_view)), withId(R.id.tab_list_view)));
+        waitForView(allOf(withParent(withId(R.id.secondary_tasks_surface_view)),
+                withId(org.chromium.chrome.tab_ui.R.id.tab_list_view)));
         assertEquals(cta.findViewById(R.id.home_button_on_tab_switcher).getVisibility(), View.GONE);
 
         StartSurfaceTestUtils.pressBack(mActivityTestRule);
@@ -240,17 +244,23 @@
 
         onViewWaiting(withId(R.id.primary_tasks_surface_view));
         onViewWaiting(withId(R.id.search_box_text));
-        onView(withId(R.id.mv_tiles_container)).check(matches(isDisplayed()));
-        onView(withId(R.id.tab_switcher_title)).check(matches(isDisplayed()));
-        onView(withId(R.id.carousel_tab_switcher_container)).check(matches(isDisplayed()));
-        onView(withId(R.id.tasks_surface_body)).check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container))
+                .check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_title))
+                .check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container))
+                .check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tasks_surface_body))
+                .check(matches(isDisplayed()));
 
         // TODO(crbug.com/1076274): fix toolbar to make incognito switch part of the view.
-        onView(withId(R.id.incognito_toggle_tabs)).check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.incognito_toggle_tabs))
+                .check(matches(withEffectiveVisibility(GONE)));
 
         StartSurfaceTestUtils.clickMoreTabs(cta);
         onViewWaiting(withId(R.id.secondary_tasks_surface_view));
-        onView(withId(R.id.incognito_toggle_tabs)).check(matches(withEffectiveVisibility(VISIBLE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.incognito_toggle_tabs))
+                .check(matches(withEffectiveVisibility(VISIBLE)));
 
         StartSurfaceTestUtils.pressBack(mActivityTestRule);
         onViewWaiting(withId(R.id.primary_tasks_surface_view));
@@ -265,7 +275,8 @@
             return;
         }
 
-        onView(withId(R.id.incognito_toggle_tabs)).check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.incognito_toggle_tabs))
+                .check(matches(withEffectiveVisibility(GONE)));
 
         StartSurfaceTestUtils.clickFirstTabInCarousel();
         LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
@@ -288,14 +299,18 @@
 
         onViewWaiting(withId(R.id.primary_tasks_surface_view));
         onViewWaiting(withId(R.id.search_box_text));
-        onView(withId(R.id.mv_tiles_container)).check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.tab_switcher_title)).check(matches(isDisplayed()));
-        onView(withId(R.id.carousel_tab_switcher_container)).check(matches(isDisplayed()));
-        onView(withId(R.id.tasks_surface_body)).check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container))
+                .check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_title))
+                .check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container))
+                .check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tasks_surface_body))
+                .check(matches(isDisplayed()));
 
         if (!isInstantReturn()) {
             // TODO(crbug.com/1076274): fix toolbar to make incognito switch part of the view.
-            onView(withId(R.id.incognito_toggle_tabs))
+            onView(withId(org.chromium.chrome.tab_ui.R.id.incognito_toggle_tabs))
                     .check(matches(withEffectiveVisibility(GONE)));
         }
 
@@ -336,18 +351,24 @@
 
         onViewWaiting(withId(R.id.primary_tasks_surface_view));
         onViewWaiting(withId(R.id.search_box_text));
-        onView(withId(R.id.mv_tiles_container)).check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.tab_switcher_title)).check(matches(withEffectiveVisibility(GONE)));
-        onView(withId(R.id.carousel_tab_switcher_container)).check(matches(isDisplayed()));
-        onView(withId(R.id.single_tab_view)).check(matches(isDisplayed()));
-        onView(withId(R.id.tasks_surface_body)).check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container))
+                .check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_title))
+                .check(matches(withEffectiveVisibility(GONE)));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container))
+                .check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.single_tab_view))
+                .check(matches(isDisplayed()));
+        onView(withId(org.chromium.chrome.tab_ui.R.id.tasks_surface_body))
+                .check(matches(isDisplayed()));
 
         if (!isInstantReturn()) {
             // TODO(crbug.com/1076274): fix toolbar to make incognito switch part of the view.
-            onView(withId(R.id.incognito_toggle_tabs))
+            onView(withId(org.chromium.chrome.tab_ui.R.id.incognito_toggle_tabs))
                     .check(matches(withEffectiveVisibility(GONE)));
         }
-        onViewWaiting(allOf(withId(R.id.tab_title_view), withText(not(is("")))));
+        onViewWaiting(allOf(
+                withId(org.chromium.chrome.tab_ui.R.id.tab_title_view), withText(not(is("")))));
 
         StartSurfaceTestUtils.clickMoreTabs(cta);
         onViewWaiting(withId(R.id.secondary_tasks_surface_view));
@@ -360,7 +381,7 @@
         StartSurfaceTestUtils.pressBack(mActivityTestRule);
         onViewWaiting(withId(R.id.primary_tasks_surface_view));
 
-        onViewWaiting(withId(R.id.single_tab_view)).perform(click());
+        onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.single_tab_view)).perform(click());
         LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
     }
 
@@ -719,7 +740,8 @@
 
         // Scroll the toolbar.
         StartSurfaceTestUtils.scrollToolbar(cta);
-        AppBarLayout taskSurfaceHeader = cta.findViewById(R.id.task_surface_header);
+        AppBarLayout taskSurfaceHeader =
+                cta.findViewById(org.chromium.chrome.tab_ui.R.id.task_surface_header);
         assertNotEquals(taskSurfaceHeader.getBottom(), taskSurfaceHeader.getHeight());
 
         // Verifies the case of scrolling Start surface ->  tab switcher -> tap "+1" button ->
@@ -747,7 +769,8 @@
         ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         StartSurfaceTestUtils.waitForOverviewVisible(
                 mLayoutChangedCallbackHelper, mCurrentlyActiveLayout);
-        onViewWaiting(allOf(withId(R.id.mv_tiles_container), isDisplayed()));
+        onViewWaiting(
+                allOf(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container), isDisplayed()));
 
         // Launches the first site in mv tiles.
         StartSurfaceTestUtils.launchFirstMVTile(cta, /* currentTabCount = */ 1);
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
index dc3b267a..cca8866 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
@@ -385,23 +385,24 @@
      */
     public static void launchFirstMVTile(ChromeTabbedActivity cta, int currentTabCount) {
         TabUiTestHelper.verifyTabModelTabCount(cta, currentTabCount, 0);
-        onViewWaiting(withId(R.id.mv_tiles_layout)).perform(new ViewAction() {
-            @Override
-            public Matcher<View> getConstraints() {
-                return isDisplayed();
-            }
+        onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_layout))
+                .perform(new ViewAction() {
+                    @Override
+                    public Matcher<View> getConstraints() {
+                        return isDisplayed();
+                    }
 
-            @Override
-            public String getDescription() {
-                return "Click explore top sites view in MV tiles.";
-            }
+                    @Override
+                    public String getDescription() {
+                        return "Click explore top sites view in MV tiles.";
+                    }
 
-            @Override
-            public void perform(UiController uiController, View view) {
-                ViewGroup mvTilesContainer = (ViewGroup) view;
-                mvTilesContainer.getChildAt(0).performClick();
-            }
-        });
+                    @Override
+                    public void perform(UiController uiController, View view) {
+                        ViewGroup mvTilesContainer = (ViewGroup) view;
+                        mvTilesContainer.getChildAt(0).performClick();
+                    }
+                });
         LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING);
         CriteriaHelper.pollUiThread(() -> !cta.getLayoutManager().overviewVisible());
         // Verifies a new Tab is created.
@@ -420,8 +421,10 @@
      * @param position The position of the tab which is clicked.
      */
     public static void clickTabInCarousel(int position) {
-        onViewWaiting(allOf(withParent(withId(R.id.carousel_tab_switcher_container)),
-                              withId(R.id.tab_list_view)))
+        onViewWaiting(
+                allOf(withParent(withId(
+                              org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container)),
+                        withId(org.chromium.chrome.tab_ui.R.id.tab_list_view)))
                 .perform(RecyclerViewActions.actionOnItemAtPosition(position, click()));
     }
 
@@ -436,7 +439,9 @@
         // TODO(crbug.com/1186752): Investigate whether this would be a problem for real users.
         try {
             TestThreadUtils.runOnUiThreadBlocking(
-                    () -> cta.findViewById(R.id.more_tabs).performClick());
+                    ()
+                            -> cta.findViewById(org.chromium.chrome.tab_ui.R.id.more_tabs)
+                                       .performClick());
         } catch (ExecutionException e) {
             fail("Failed to tap 'more tabs' " + e.toString());
         }
diff --git a/chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni b/chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni
index 980b80b0..c8326b0 100644
--- a/chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni
+++ b/chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni
@@ -21,6 +21,4 @@
   "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java",
   "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java",
   "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinderTest.java",
-  "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/tasks/SingleTabViewBinderTest.java",
-  "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/tasks/TasksViewBinderTest.java",
 ]
diff --git a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java b/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
index db3d67e..2493f8c8 100644
--- a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
+++ b/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
@@ -24,23 +24,23 @@
 import static org.mockito.Mockito.when;
 
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.INSTANT_START;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_INITIALIZED;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MV_TILES_CONTAINER_TOP_MARGIN;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MV_TILES_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.TAB_SWITCHER_TITLE_TOP_MARGIN;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.TASKS_SURFACE_BODY_TOP_MARGIN;
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.BOTTOM_BAR_HEIGHT;
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.EXPLORE_SURFACE_COORDINATOR;
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_EXPLORE_SURFACE_VISIBLE;
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_SECONDARY_SURFACE_VISIBLE;
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_SHOWING_OVERVIEW;
 import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_INITIALIZED;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.MV_TILES_CONTAINER_TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.MV_TILES_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TAB_SWITCHER_TITLE_TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TASKS_SURFACE_BODY_TOP_MARGIN;
 
 import android.content.res.Resources;
 import android.view.View;
@@ -78,11 +78,11 @@
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
+import org.chromium.chrome.browser.tasks.TasksSurfaceProperties;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegate.TabSwitcherType;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher.OverviewModeObserver;
 import org.chromium.chrome.features.start_surface.StartSurfaceMediator.SecondaryTasksSurfaceInitializer;
-import org.chromium.chrome.features.tasks.TasksSurfaceProperties;
 import org.chromium.chrome.start_surface.R;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.components.prefs.PrefService;
diff --git a/chrome/android/features/start_surface/internal/junit/start_surface_junit_java_sources.gni b/chrome/android/features/start_surface/internal/junit/start_surface_junit_java_sources.gni
index f10b77c..3ec8817 100644
--- a/chrome/android/features/start_surface/internal/junit/start_surface_junit_java_sources.gni
+++ b/chrome/android/features/start_surface/internal/junit/start_surface_junit_java_sources.gni
@@ -2,8 +2,4 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-start_surface_junit_java_sources = [
-  "//chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java",
-  "//chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediatorUnitTest.java",
-  "//chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/tasks/TasksSurfaceMediatorUnitTest.java",
-]
+start_surface_junit_java_sources = [ "//chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java" ]
diff --git a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java
index 981fc50..e051a99e 100644
--- a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java
+++ b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java
@@ -13,8 +13,8 @@
 
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin;
+import org.chromium.chrome.browser.tasks.TasksSurface;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
-import org.chromium.chrome.features.tasks.TasksSurface;
 
 /** Interface to communicate with the start surface. */
 public interface StartSurface {
diff --git a/chrome/android/features/start_surface/public/start_surface_public_java_sources.gni b/chrome/android/features/start_surface/public/start_surface_public_java_sources.gni
index 905c8113..16e70d9 100644
--- a/chrome/android/features/start_surface/public/start_surface_public_java_sources.gni
+++ b/chrome/android/features/start_surface/public/start_surface_public_java_sources.gni
@@ -3,7 +3,4 @@
 # found in the LICENSE file.
 
 # TODO: Move this to the target public_java too.
-start_surface_public_java_sources = [
-  "//chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java",
-  "//chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/tasks/TasksSurface.java",
-]
+start_surface_public_java_sources = [ "//chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java" ]
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn
index f924036d..bd61110 100644
--- a/chrome/android/features/tab_ui/BUILD.gn
+++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -45,6 +45,7 @@
     "java/res/drawable/price_card_scrim.xml",
     "java/res/drawable/selected_tab_background.xml",
     "java/res/drawable/selected_tab_background_incognito.xml",
+    "java/res/drawable/single_tab_background.xml",
     "java/res/drawable/tab_grid_card_background.xml",
     "java/res/drawable/tab_grid_dialog_background.xml",
     "java/res/drawable/tab_grid_selection_list_icon.xml",
@@ -65,8 +66,10 @@
     "java/res/layout/new_tab_tile_card_item.xml",
     "java/res/layout/price_card.xml",
     "java/res/layout/price_tracking_dialog_layout.xml",
+    "java/res/layout/query_tiles_layout.xml",
     "java/res/layout/selectable_tab_grid_card_item.xml",
     "java/res/layout/selectable_tab_list_card_item.xml",
+    "java/res/layout/single_tab_view_layout.xml",
     "java/res/layout/store_hours_card.xml",
     "java/res/layout/tab_grid_card_item.xml",
     "java/res/layout/tab_grid_dialog_layout.xml",
@@ -76,6 +79,8 @@
     "java/res/layout/tab_selection_editor_layout.xml",
     "java/res/layout/tab_selection_editor_toolbar.xml",
     "java/res/layout/tab_strip_item.xml",
+    "java/res/layout/tasks_surface_search_box_layout.xml",
+    "java/res/layout/tasks_view_layout.xml",
     "java/res/values/attrs.xml",
     "java/res/values/colors.xml",
     "java/res/values/dimens.xml",
@@ -91,6 +96,15 @@
 
 android_library("java") {
   sources = [
+    "java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherCoordinator.java",
+    "java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediator.java",
+    "java/src/org/chromium/chrome/browser/tasks/SingleTabView.java",
+    "java/src/org/chromium/chrome/browser/tasks/SingleTabViewBinder.java",
+    "java/src/org/chromium/chrome/browser/tasks/SingleTabViewProperties.java",
+    "java/src/org/chromium/chrome/browser/tasks/TasksSurfaceCoordinator.java",
+    "java/src/org/chromium/chrome/browser/tasks/TasksSurfaceMediator.java",
+    "java/src/org/chromium/chrome/browser/tasks/TasksView.java",
+    "java/src/org/chromium/chrome/browser/tasks/TasksViewBinder.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtils.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/ClosableTabGridView.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageCardViewModel.java",
@@ -138,6 +152,7 @@
     "java/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerProperties.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinder.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java",
+    "java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/TabListModel.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java",
@@ -156,6 +171,7 @@
     "java/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageService.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java",
+    "java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/BaselineTabSuggestionProvider.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/StaleTabSuggestionProvider.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContextObserver.java",
@@ -172,6 +188,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/android:ui_locale_string_resources",
     "//chrome/android/features/start_surface:public_java",
@@ -182,6 +199,7 @@
     "//chrome/browser/endpoint_fetcher:java",
     "//chrome/browser/feature_engagement:java",
     "//chrome/browser/feed/android:java",
+    "//chrome/browser/feedback/android:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/lens:java",
     "//chrome/browser/preferences:java",
@@ -205,6 +223,7 @@
     "//components/browser_ui/share/android:java",
     "//components/browser_ui/styles/android:java",
     "//components/browser_ui/widget/android:java",
+    "//components/content_settings/android:content_settings_enums_java",
     "//components/embedder_support/android:util_java",
     "//components/embedder_support/android:web_contents_delegate_java",
     "//components/favicon/android:java",
@@ -221,6 +240,7 @@
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
     "//third_party/androidx:androidx_appcompat_appcompat_resources_java",
+    "//third_party/androidx:androidx_coordinatorlayout_coordinatorlayout_java",
     "//third_party/androidx:androidx_core_core_java",
     "//third_party/androidx:androidx_lifecycle_lifecycle_runtime_java",
     "//third_party/androidx:androidx_recyclerview_recyclerview_java",
diff --git a/chrome/android/features/start_surface/internal/java/res/drawable/single_tab_background.xml b/chrome/android/features/tab_ui/java/res/drawable/single_tab_background.xml
similarity index 100%
rename from chrome/android/features/start_surface/internal/java/res/drawable/single_tab_background.xml
rename to chrome/android/features/tab_ui/java/res/drawable/single_tab_background.xml
diff --git a/chrome/android/features/start_surface/internal/java/res/layout/query_tiles_layout.xml b/chrome/android/features/tab_ui/java/res/layout/query_tiles_layout.xml
similarity index 100%
rename from chrome/android/features/start_surface/internal/java/res/layout/query_tiles_layout.xml
rename to chrome/android/features/tab_ui/java/res/layout/query_tiles_layout.xml
diff --git a/chrome/android/features/start_surface/internal/java/res/layout/single_tab_view_layout.xml b/chrome/android/features/tab_ui/java/res/layout/single_tab_view_layout.xml
similarity index 96%
rename from chrome/android/features/start_surface/internal/java/res/layout/single_tab_view_layout.xml
rename to chrome/android/features/tab_ui/java/res/layout/single_tab_view_layout.xml
index 257896a..7f04784 100644
--- a/chrome/android/features/start_surface/internal/java/res/layout/single_tab_view_layout.xml
+++ b/chrome/android/features/tab_ui/java/res/layout/single_tab_view_layout.xml
@@ -3,7 +3,7 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<org.chromium.chrome.features.tasks.SingleTabView
+<org.chromium.chrome.browser.tasks.SingleTabView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
@@ -76,4 +76,4 @@
     </RelativeLayout>
 
 
-</org.chromium.chrome.features.tasks.SingleTabView>
+</org.chromium.chrome.browser.tasks.SingleTabView>
diff --git a/chrome/android/features/start_surface/internal/java/res/layout/tasks_surface_search_box_layout.xml b/chrome/android/features/tab_ui/java/res/layout/tasks_surface_search_box_layout.xml
similarity index 100%
rename from chrome/android/features/start_surface/internal/java/res/layout/tasks_surface_search_box_layout.xml
rename to chrome/android/features/tab_ui/java/res/layout/tasks_surface_search_box_layout.xml
diff --git a/chrome/android/features/start_surface/internal/java/res/layout/tasks_view_layout.xml b/chrome/android/features/tab_ui/java/res/layout/tasks_view_layout.xml
similarity index 97%
rename from chrome/android/features/start_surface/internal/java/res/layout/tasks_view_layout.xml
rename to chrome/android/features/tab_ui/java/res/layout/tasks_view_layout.xml
index 61a87be..f5a6dc20 100644
--- a/chrome/android/features/start_surface/internal/java/res/layout/tasks_view_layout.xml
+++ b/chrome/android/features/tab_ui/java/res/layout/tasks_view_layout.xml
@@ -3,7 +3,7 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<org.chromium.chrome.features.tasks.TasksView
+<org.chromium.chrome.browser.tasks.TasksView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
@@ -101,4 +101,4 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         app:layout_behavior="@string/appbar_scrolling_view_behavior" />
-</org.chromium.chrome.features.tasks.TasksView>
+</org.chromium.chrome.browser.tasks.TasksView>
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherCoordinator.java
similarity index 98%
rename from chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java
rename to chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherCoordinator.java
index 29d483b..a0531f7 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherCoordinator.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
 import android.app.Activity;
 import android.content.Context;
@@ -25,7 +25,7 @@
 import org.chromium.chrome.browser.tasks.tab_management.TabListFaviconProvider;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
-import org.chromium.chrome.start_surface.R;
+import org.chromium.chrome.tab_ui.R;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediator.java
similarity index 96%
rename from chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediator.java
rename to chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediator.java
index 7667151..26dcee50 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediator.java
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.FAVICON;
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.IS_VISIBLE;
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.TITLE;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.FAVICON;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.IS_VISIBLE;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.TITLE;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
@@ -31,7 +31,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
-import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
 import org.chromium.chrome.browser.tasks.pseudotab.PseudoTab;
 import org.chromium.chrome.browser.tasks.tab_management.TabListFaviconProvider;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegate.TabSwitcherType;
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabView.java
similarity index 93%
rename from chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabView.java
rename to chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabView.java
index 0c794405..fb5fae19 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabView.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabView.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
@@ -11,7 +11,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
-import org.chromium.chrome.start_surface.R;
+import org.chromium.chrome.tab_ui.R;
 
 /** View of the tab on the single tab tab switcher. */
 class SingleTabView extends LinearLayout {
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabViewBinder.java
similarity index 71%
rename from chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabViewBinder.java
rename to chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabViewBinder.java
index 5e357a4..329fd63 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabViewBinder.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabViewBinder.java
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.FAVICON;
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.IS_VISIBLE;
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.TITLE;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.FAVICON;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.IS_VISIBLE;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.TITLE;
 
 import android.view.View;
 
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabViewProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabViewProperties.java
similarity index 96%
rename from chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabViewProperties.java
rename to chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabViewProperties.java
index ab37fa1e..1fb4553 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/SingleTabViewProperties.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabViewProperties.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
 import android.graphics.drawable.Drawable;
 import android.view.View;
diff --git a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/tasks/TasksSurface.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurface.java
similarity index 98%
rename from chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/tasks/TasksSurface.java
rename to chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurface.java
index 875264c..e1261a9a 100644
--- a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/tasks/TasksSurface.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurface.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
 import android.content.Context;
 import android.view.View;
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceCoordinator.java
similarity index 98%
rename from chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
rename to chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceCoordinator.java
index c1fcfe6..dcb4b208 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceCoordinator.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
 import android.app.Activity;
 import android.content.Context;
@@ -42,7 +42,7 @@
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
-import org.chromium.chrome.start_surface.R;
+import org.chromium.chrome.tab_ui.R;
 import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController;
 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
 import org.chromium.ui.base.DeviceFormFactor;
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceMediator.java
similarity index 76%
rename from chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceMediator.java
rename to chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceMediator.java
index 6ee57c4..9a0518e 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceMediator.java
@@ -2,24 +2,24 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_ICON_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_ENFORCEMENT;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_LENS_BUTTON_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_SURFACE_BODY_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.LENS_BUTTON_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.VOICE_SEARCH_BUTTON_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_ICON_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_ENFORCEMENT;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_LENS_BUTTON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_SURFACE_BODY_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.LENS_BUTTON_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.VOICE_SEARCH_BUTTON_CLICK_LISTENER;
 
 import android.text.Editable;
 import android.text.TextWatcher;
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceProperties.java
similarity index 98%
rename from chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceProperties.java
rename to chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceProperties.java
index 6a4a19b..2a95e40 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksSurfaceProperties.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceProperties.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
 import static org.chromium.chrome.browser.suggestions.tile.MostVisitedTilesProperties.IS_CONTAINER_VISIBLE;
 
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksView.java
similarity index 99%
rename from chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksView.java
rename to chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksView.java
index a4ef52a1..1dba418 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksView.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksView.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
 import android.app.Activity;
 import android.content.Context;
@@ -35,7 +35,7 @@
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.ntp.IncognitoDescriptionView;
 import org.chromium.chrome.browser.ntp.search.SearchBoxCoordinator;
-import org.chromium.chrome.start_surface.R;
+import org.chromium.chrome.tab_ui.R;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.components.browser_ui.widget.CoordinatorLayoutForPointer;
 import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksViewBinder.java
similarity index 65%
rename from chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksViewBinder.java
rename to chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksViewBinder.java
index a3bf10e..bf8e642b 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/tasks/TasksViewBinder.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksViewBinder.java
@@ -2,35 +2,35 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_ICON_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_ENFORCEMENT;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_INITIALIZED;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_LENS_BUTTON_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_SURFACE_BODY_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.LENS_BUTTON_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.MORE_TABS_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.MV_TILES_CONTAINER_TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.MV_TILES_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.QUERY_TILES_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.RESET_TASK_SURFACE_HEADER_SCROLL_POSITION;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TAB_SWITCHER_TITLE_TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TASKS_SURFACE_BODY_TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TOP_TOOLBAR_PLACEHOLDER_HEIGHT;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.VOICE_SEARCH_BUTTON_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_ICON_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_CHECKED_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_TOGGLE_ENFORCEMENT;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_INITIALIZED;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_LENS_BUTTON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_SURFACE_BODY_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.LENS_BUTTON_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MORE_TABS_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MV_TILES_CONTAINER_TOP_MARGIN;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MV_TILES_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.QUERY_TILES_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.RESET_TASK_SURFACE_HEADER_SCROLL_POSITION;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.TAB_SWITCHER_TITLE_TOP_MARGIN;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.TASKS_SURFACE_BODY_TOP_MARGIN;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.TOP_TOOLBAR_PLACEHOLDER_HEIGHT;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.VOICE_SEARCH_BUTTON_CLICK_LISTENER;
 
 import android.view.View;
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
index 6e57b5b..f1dad7b 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
@@ -33,6 +33,8 @@
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tasks.TasksSurface;
+import org.chromium.chrome.browser.tasks.TasksSurfaceProperties;
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
 import org.chromium.chrome.browser.tasks.tab_management.suggestions.TabSuggestions;
 import org.chromium.chrome.browser.toolbar.top.Toolbar;
@@ -44,6 +46,7 @@
 import org.chromium.components.module_installer.builder.ModuleInterface;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.modaldialog.ModalDialogManager;
+import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
 
 import java.lang.annotation.Retention;
@@ -67,6 +70,47 @@
     }
 
     /**
+     * Create the {@link TasksSurface}
+     * @param activity The {@link Activity} that creates this surface.
+     * @param scrimCoordinator The {@link ScrimCoordinator} that controls scrim view.
+     * @param propertyModel The {@link PropertyModel} contains the {@link TasksSurfaceProperties}
+     *         to communicate with this surface.
+     * @param tabSwitcherType The type of the tab switcher to show.
+     * @param parentTabSupplier {@link Supplier} to provide parent tab for the
+     *         TasksSurface.
+     * @param hasMVTiles whether has MV tiles on the surface.
+     * @param windowAndroid An instance of a {@link WindowAndroid}.
+     * @param activityLifecycleDispatcher Allows observation of the activity lifecycle.
+     * @param tabModelSelector Gives access to the current set of {@TabModel}.
+     * @param snackbarManager Manages the display of snackbars.
+     * @param dynamicResourceLoaderSupplier Supplies the current {@link DynamicResourceLoader}.
+     * @param tabContentManager Gives access to the tab content.
+     * @param modalDialogManager Manages the display of modal dialogs.
+     * @param browserControlsStateProvider Gives access to the state of the browser controls.
+     * @param tabCreatorManger Manages creation of tabs.
+     * @param menuOrKeyboardActionController allows access to menu or keyboard actions.
+     * @param shareDelegateSupplier Supplies the current {@link ShareDelegate}.
+     * @param multiWindowModeStateDispatcher Gives access to the multi window mode state.
+     * @param rootView The root view of the app.
+     * @return The {@link TasksSurface}.
+     */
+    TasksSurface createTasksSurface(@NonNull Activity activity,
+            @NonNull ScrimCoordinator scrimCoordinator, @NonNull PropertyModel propertyModel,
+            @TabSwitcherType int tabSwitcherType, @NonNull Supplier<Tab> parentTabSupplier,
+            boolean hasMVTiles, boolean hasQueryTiles, @NonNull WindowAndroid windowAndroid,
+            @NonNull ActivityLifecycleDispatcher activityLifecycleDispatcher,
+            @NonNull TabModelSelector tabModelSelector, @NonNull SnackbarManager snackbarManager,
+            @NonNull Supplier<DynamicResourceLoader> dynamicResourceLoaderSupplier,
+            @NonNull TabContentManager tabContentManager,
+            @NonNull ModalDialogManager modalDialogManager,
+            @NonNull BrowserControlsStateProvider browserControlsStateProvider,
+            @NonNull TabCreatorManager tabCreatorManager,
+            @NonNull MenuOrKeyboardActionController menuOrKeyboardActionController,
+            @NonNull Supplier<ShareDelegate> shareDelegateSupplier,
+            @NonNull MultiWindowModeStateDispatcher multiWindowModeStateDispatcher,
+            @NonNull ViewGroup rootView);
+
+    /**
      * Create the {@link TabSwitcher} to display Tabs in grid.
      * @param activity The current android {@link Activity}.
      * @param activityLifecycleDispatcher Allows observation of the activity lifecycle.
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
index c182fbf..6a23f0e 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
@@ -38,6 +38,8 @@
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tasks.TasksSurface;
+import org.chromium.chrome.browser.tasks.TasksSurfaceCoordinator;
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
 import org.chromium.chrome.browser.tasks.tab_management.suggestions.TabSuggestions;
 import org.chromium.chrome.browser.tasks.tab_management.suggestions.TabSuggestionsOrchestrator;
@@ -50,6 +52,7 @@
 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.modaldialog.ModalDialogManager;
+import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
 
 /**
@@ -58,6 +61,30 @@
 @UsedByReflection("TabManagementModule")
 public class TabManagementDelegateImpl implements TabManagementDelegate {
     @Override
+    public TasksSurface createTasksSurface(@NonNull Activity activity,
+            @NonNull ScrimCoordinator scrimCoordinator, @NonNull PropertyModel propertyModel,
+            @TabSwitcherType int tabSwitcherType, @NonNull Supplier<Tab> parentTabSupplier,
+            boolean hasMVTiles, boolean hasQueryTiles, @NonNull WindowAndroid windowAndroid,
+            @NonNull ActivityLifecycleDispatcher activityLifecycleDispatcher,
+            @NonNull TabModelSelector tabModelSelector, @NonNull SnackbarManager snackbarManager,
+            @NonNull Supplier<DynamicResourceLoader> dynamicResourceLoaderSupplier,
+            @NonNull TabContentManager tabContentManager,
+            @NonNull ModalDialogManager modalDialogManager,
+            @NonNull BrowserControlsStateProvider browserControlsStateProvider,
+            @NonNull TabCreatorManager tabCreatorManager,
+            @NonNull MenuOrKeyboardActionController menuOrKeyboardActionController,
+            @NonNull Supplier<ShareDelegate> shareDelegateSupplier,
+            @NonNull MultiWindowModeStateDispatcher multiWindowModeStateDispatcher,
+            @NonNull ViewGroup rootView) {
+        return new TasksSurfaceCoordinator(activity, scrimCoordinator, propertyModel,
+                tabSwitcherType, parentTabSupplier, hasMVTiles, hasQueryTiles, windowAndroid,
+                activityLifecycleDispatcher, tabModelSelector, snackbarManager,
+                dynamicResourceLoaderSupplier, tabContentManager, modalDialogManager,
+                browserControlsStateProvider, tabCreatorManager, menuOrKeyboardActionController,
+                shareDelegateSupplier, multiWindowModeStateDispatcher, rootView);
+    }
+
+    @Override
     public TabSwitcher createGridTabSwitcher(@NonNull Activity activity,
             @NonNull ActivityLifecycleDispatcher activityLifecycleDispatcher,
             @NonNull TabModelSelector tabModelSelector,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
index 30563d0..3d0d8b02 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
@@ -59,7 +59,7 @@
             float tabElevation = context.getResources().getDimension(R.dimen.tab_bg_elevation);
             @ColorInt
             int colorInt = isSelected
-                    ? MaterialColors.getColor(context, org.chromium.chrome.R.attr.colorPrimary, TAG)
+                    ? MaterialColors.getColor(context, R.attr.colorPrimary, TAG)
                     : new ElevationOverlayProvider(context)
                               .compositeOverlayWithThemeSurfaceColorIfNeeded(tabElevation);
             return colorInt;
@@ -195,8 +195,7 @@
             return AppCompatResources.getColorStateList(
                     context, R.color.incognito_tab_bg_selected_color);
         }
-        return ColorStateList.valueOf(
-                MaterialColors.getColor(context, org.chromium.chrome.R.attr.colorPrimary, TAG));
+        return ColorStateList.valueOf(MaterialColors.getColor(context, R.attr.colorPrimary, TAG));
     }
 
     /**
@@ -357,8 +356,7 @@
         } else {
             if (isSelected) {
                 @ColorInt
-                int baseColor = MaterialColors.getColor(
-                        context, org.chromium.chrome.R.attr.colorPrimary, TAG);
+                int baseColor = MaterialColors.getColor(context, R.attr.colorPrimary, TAG);
                 int alpha = context.getResources().getInteger(
                         R.integer.tab_grid_hovered_card_background_selected_color_alpha);
                 return ColorStateList.valueOf(
@@ -421,9 +419,8 @@
                             ? R.color.incognito_tab_grid_dialog_ungroup_bar_bg_hovered_color
                             : R.color.incognito_tab_grid_dialog_background_color);
         } else {
-            return MaterialColors.getColor(context,
-                    isTabHovered ? org.chromium.chrome.R.attr.colorPrimary : R.attr.colorSurface,
-                    TAG);
+            return MaterialColors.getColor(
+                    context, isTabHovered ? R.attr.colorPrimary : R.attr.colorSurface, TAG);
         }
     }
 
@@ -447,9 +444,8 @@
                             ? R.color.incognito_tab_grid_dialog_ungroup_bar_text_hovered_color
                             : R.color.incognito_tab_grid_dialog_ungroup_bar_text_color);
         } else {
-            return MaterialColors.getColor(context,
-                    isTabHovered ? R.attr.colorOnPrimary : org.chromium.chrome.R.attr.colorPrimary,
-                    TAG);
+            return MaterialColors.getColor(
+                    context, isTabHovered ? R.attr.colorOnPrimary : R.attr.colorPrimary, TAG);
         }
     }
 
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/tasks/SingleTabViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java
similarity index 90%
rename from chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/tasks/SingleTabViewBinderTest.java
rename to chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java
index 2657991..da45b80 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/tasks/SingleTabViewBinderTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -12,10 +12,10 @@
 import static org.mockito.ArgumentMatchers.anyObject;
 import static org.mockito.Mockito.verify;
 
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.FAVICON;
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.IS_VISIBLE;
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.TITLE;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.FAVICON;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.IS_VISIBLE;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.TITLE;
 
 import android.graphics.drawable.BitmapDrawable;
 import android.view.View;
@@ -30,7 +30,7 @@
 import org.mockito.MockitoAnnotations;
 
 import org.chromium.base.test.UiThreadTest;
-import org.chromium.chrome.start_surface.R;
+import org.chromium.chrome.tab_ui.R;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.modelutil.PropertyModel;
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/tasks/TasksViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java
similarity index 83%
rename from chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/tasks/TasksViewBinderTest.java
rename to chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java
index 98b91fc..e45c334 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/tasks/TasksViewBinderTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
 import static androidx.test.espresso.Espresso.onView;
 import static androidx.test.espresso.action.ViewActions.click;
@@ -13,26 +13,26 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_INITIALIZED;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_LENS_BUTTON_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.LENS_BUTTON_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.MORE_TABS_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.MV_TILES_CONTAINER_TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.MV_TILES_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TAB_SWITCHER_TITLE_TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TASKS_SURFACE_BODY_TOP_MARGIN;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.TOP_TOOLBAR_PLACEHOLDER_HEIGHT;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.VOICE_SEARCH_BUTTON_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_INITIALIZED;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_LENS_BUTTON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.LENS_BUTTON_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MORE_TABS_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MV_TILES_CONTAINER_TOP_MARGIN;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MV_TILES_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.TAB_SWITCHER_TITLE_TOP_MARGIN;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.TASKS_SURFACE_BODY_TOP_MARGIN;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.TOP_TOOLBAR_PLACEHOLDER_HEIGHT;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.VOICE_SEARCH_BUTTON_CLICK_LISTENER;
 
 import android.graphics.drawable.ColorDrawable;
 import android.text.Editable;
@@ -51,7 +51,7 @@
 import org.chromium.base.test.UiThreadTest;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.chrome.browser.ntp.IncognitoCookieControlsManager;
-import org.chromium.chrome.start_surface.R;
+import org.chromium.chrome.tab_ui.R;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -251,7 +251,8 @@
 
     @Test
     @SmallTest
-    public void testSetIncognitoDescriptionVisibilityAndClickListener() {
+    public void
+    testSetIncognitoDescriptionVisibilityAndClickListener() {
         assertFalse(isViewVisible(R.id.incognito_description_container_layout_stub));
 
         TestThreadUtils.runOnUiThreadBlocking(() -> {
@@ -265,6 +266,7 @@
             mTasksViewPropertyModel.set(IS_INCOGNITO_DESCRIPTION_VISIBLE, true);
         });
         assertTrue(isViewVisible(R.id.new_tab_incognito_container));
+
     }
 
     @Test
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
index 7658896e..389a933 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
@@ -927,8 +927,7 @@
         // Tab switcher is created, and the dummy signal to hide dialog is sent. This line would
         // crash if the dummy signal is not properly handled. See crbug.com/1096358.
         enterTabSwitcher(cta);
-        onView(allOf(withParent(withId(org.chromium.chrome.start_surface.R.id.tasks_surface_body)),
-                       withId(R.id.tab_list_view)))
+        onView(allOf(withParent(withId(R.id.tasks_surface_body)), withId(R.id.tab_list_view)))
                 .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
         CriteriaHelper.pollUiThread(() -> isDialogShowing(mActivityTestRule.getActivity()));
         verifyShowingDialog(cta, 2, null);
@@ -967,8 +966,7 @@
 
         // Test undo closure in dialog from StartSurface tab switcher.
         enterTabSwitcher(cta);
-        onView(allOf(withParent(withId(org.chromium.chrome.start_surface.R.id.tasks_surface_body)),
-                       withId(R.id.tab_list_view)))
+        onView(allOf(withParent(withId(R.id.tasks_surface_body)), withId(R.id.tab_list_view)))
                 .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
         CriteriaHelper.pollUiThread(() -> isDialogShowing(cta));
         verifyShowingDialog(cta, 2, null);
@@ -980,8 +978,7 @@
         // Test undo closure in dialog from StartSurface home page.
         clickScrimToExitDialog(cta);
         onView(withId(org.chromium.chrome.start_surface.R.id.new_tab_button)).perform(click());
-        onView(allOf(withParent(withId(org.chromium.chrome.start_surface.R.id
-                                               .carousel_tab_switcher_container)),
+        onView(allOf(withParent(withId(R.id.carousel_tab_switcher_container)),
                        withId(R.id.tab_list_view)))
                 .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
         CriteriaHelper.pollUiThread(() -> isDialogShowing(cta));
diff --git a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediatorUnitTest.java
similarity index 97%
rename from chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediatorUnitTest.java
rename to chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediatorUnitTest.java
index 1f12443..cbfdb67d 100644
--- a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/tasks/SingleTabSwitcherMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediatorUnitTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -14,9 +14,9 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.FAVICON;
-import static org.chromium.chrome.features.tasks.SingleTabViewProperties.TITLE;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.FAVICON;
+import static org.chromium.chrome.browser.tasks.SingleTabViewProperties.TITLE;
 
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
diff --git a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/tasks/TasksSurfaceMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/TasksSurfaceMediatorUnitTest.java
similarity index 83%
rename from chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/tasks/TasksSurfaceMediatorUnitTest.java
rename to chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/TasksSurfaceMediatorUnitTest.java
index 0c28c79..837c1a5 100644
--- a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/tasks/TasksSurfaceMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/TasksSurfaceMediatorUnitTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.features.tasks;
+package org.chromium.chrome.browser.tasks;
 
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -14,18 +14,18 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_INITIALIZED;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_SURFACE_BODY_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
-import static org.chromium.chrome.features.tasks.TasksSurfaceProperties.VOICE_SEARCH_BUTTON_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_TEXT_WATCHER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_COOKIE_CONTROLS_MANAGER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.INCOGNITO_LEARN_MORE_CLICK_LISTENER;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_INITIALIZED;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_INCOGNITO_DESCRIPTION_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_SURFACE_BODY_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_TITLE_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.VOICE_SEARCH_BUTTON_CLICK_LISTENER;
 
 import android.text.Editable;
 import android.text.TextWatcher;
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni
index 19c358c..695a5e7 100644
--- a/chrome/android/features/tab_ui/tab_management_java_sources.gni
+++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -2,7 +2,12 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import(
+    "//chrome/android/features/start_surface/public/start_surface_public_java_sources.gni")
+
 public_tab_management_java_sources = [
+  "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurface.java",
+  "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksSurfaceProperties.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/mv_tiles/MostVisitedTileNavigationDelegate.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCache.java",
@@ -10,12 +15,10 @@
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingUtilities.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/StoreTrackingUtilities.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUi.java",
-  "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementModuleProvider.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java",
-  "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/UndoGroupSnackbarController.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContext.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestion.java",
@@ -24,7 +27,11 @@
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsObserver.java",
 ]
 
+public_tab_management_java_sources += start_surface_public_java_sources
+
 tab_management_test_java_sources = [
+  "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java",
+  "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/AssertsTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsDialogTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/LargeMessageCardViewBinderTest.java",
@@ -56,6 +63,8 @@
 ]
 
 tab_management_junit_java_sources = [
+  "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediatorUnitTest.java",
+  "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/TasksSurfaceMediatorUnitTest.java",
   "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java",
   "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCacheUnitTest.java",
   "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtilsUnitTest.java",
diff --git a/chrome/android/features/vr/BUILD.gn b/chrome/android/features/vr/BUILD.gn
index 3523f9e..d9793c1 100644
--- a/chrome/android/features/vr/BUILD.gn
+++ b/chrome/android/features/vr/BUILD.gn
@@ -70,6 +70,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//cc:cc_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/feedback/android:java",
diff --git a/chrome/android/java/res/layout/fullscreen_notification.xml b/chrome/android/java/res/layout/fullscreen_notification.xml
index 5687b66a..3a12ad5 100644
--- a/chrome/android/java/res/layout/fullscreen_notification.xml
+++ b/chrome/android/java/res/layout/fullscreen_notification.xml
@@ -4,10 +4,12 @@
      found in the LICENSE file. -->
 
 <LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
+  xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/fullscreen_notification"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
+    android:gravity="center"
     android:paddingTop="24dp">
     <TextView
         android:id="@+id/text"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
index cb5fd15..48d6f9c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -19,6 +19,7 @@
 import org.chromium.chrome.browser.optimization_guide.OptimizationGuidePushNotificationManager;
 import org.chromium.chrome.browser.page_annotations.PageAnnotationsServiceConfig;
 import org.chromium.chrome.browser.paint_preview.StartupPaintPreviewHelper;
+import org.chromium.chrome.browser.paint_preview.services.PaintPreviewTabService;
 import org.chromium.chrome.browser.tasks.ConditionalTabStripUtils;
 import org.chromium.chrome.browser.tasks.ReturnToChromeUtil;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities;
@@ -162,6 +163,7 @@
                         add(StartSurfaceConfiguration.USER_CLICK_THRESHOLD);
                         add(StartSurfaceConfiguration.WARM_UP_RENDERER);
                         add(StartupPaintPreviewHelper.ACCESSIBILITY_SUPPORT_PARAM);
+                        add(PaintPreviewTabService.ALLOW_SRP);
                         add(TabContentManager.ALLOW_TO_REFETCH_TAB_THUMBNAIL_VARIATION);
                         add(TabUiFeatureUtilities.ENABLE_LAUNCH_BUG_FIX);
                         add(TabUiFeatureUtilities.ENABLE_LAUNCH_POLISH);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditor.java
index 0ae0f90..ea27b1b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditor.java
@@ -184,8 +184,9 @@
     private void setVirtualCardEnrollmentButtonLabel(boolean isEnrolled) {
         mVirtualCardEnrollmentButtonShowsUnenroll = isEnrolled;
         mVirtualCardEnrollmentButton.setEnabled(true);
-        mVirtualCardEnrollmentButton.setText(
-                mVirtualCardEnrollmentButtonShowsUnenroll ? R.string.remove : R.string.add);
+        mVirtualCardEnrollmentButton.setText(mVirtualCardEnrollmentButtonShowsUnenroll
+                        ? R.string.autofill_card_editor_virtual_card_turn_off_button_label
+                        : R.string.autofill_card_editor_virtual_card_turn_on_button_label);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandler.java
index 0b83162..53cc2df 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandler.java
@@ -22,6 +22,7 @@
 import android.view.WindowManager;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.core.util.ObjectsCompat;
 
 import org.chromium.base.ActivityState;
@@ -76,6 +77,8 @@
     private static final long CLEAR_LAYOUT_FULLSCREEN_DELAY_MS = 20;
     // Fade in/out animation duration for fullscreen notification toast.
     private static final int TOAST_FADE_MS = 500;
+    // Time that the notification toast remains on-screen before starting to fade out.
+    private static final int TOAST_SHOW_DURATION_MS = 5000;
 
     private final Activity mActivity;
     private final Handler mHandler;
@@ -98,12 +101,33 @@
 
     // Toast at the top of the screen that is shown when user enters fullscreen for the
     // first time.
+    //
+    // This is whether we believe that we need to show the user a notification toast.  It's false if
+    // we're not in full screen, or if we are in full screen but have already shown the toast for
+    // enough time for the user to read it.  The toast might or might not actually be on-screen
+    // right now; we remove it in some cases like when we lose window focus.  However, as long as
+    // we'll be in full screen, we still keep the toast pending until we successfully show it.
+    private boolean mIsNotificationToastPending;
+
+    // Sometimes, the toast must be removed temporarily, such as when we lose focus or if we
+    // transition to picture-in-picture.  In those cases, the toast is removed from the view
+    // hierarchy, and these fields are cleared.  The toast will be re-created from scratch when it's
+    // appropriate to show it again.  `mIsNotificationToastPending` won't be reset in those cases,
+    // though, since we'll still want to show the toast when it's possible to do so.
+    //
+    // If `mNotificationToast` exists, then it's attached to the view hierarchy, though it might be
+    // animating to or from alpha=0.  Any time the toast exists, we also have an animation for it,
+    // to allow us to fade it in, and eventually back out.  The animation is not cleared when it
+    // completes; it's only cleared when we also detach the toast and clear `mNotificationToast`.
+    //
+    // Importantly, it's possible that `mNotificationToast` is not null while no toast is pending.
+    // This can happen when the toast has been on-screen long enough, and is fading out.
     private View mNotificationToast;
-    private long mNotificationStartTimestamp;
-    private long mNotificationRemainingTimeMs;
-    private final Runnable mHideNotificationToastRunnable;
     private ViewPropertyAnimator mToastFadeAnimation;
 
+    // Runnable that will complete the current toast and fade it out.
+    private final Runnable mFadeOutNotificationToastRunnable;
+
     private OnLayoutChangeListener mFullscreenOnLayoutChangeListener;
 
     private FullscreenOptions mPendingFullscreenOptions;
@@ -224,7 +248,7 @@
         mPersistentModeSupplier = new ObservableSupplierImpl<>();
         mPersistentModeSupplier.set(false);
         mExitFullscreenOnStop = exitFullscreenOnStop;
-        mHideNotificationToastRunnable = this::hideNotificationToast;
+        mFadeOutNotificationToastRunnable = this::fadeOutNotificationToast;
     }
 
     /**
@@ -338,7 +362,8 @@
         }
     }
 
-    private void destroySelectActionMode(Tab tab) {
+    @VisibleForTesting
+    /* package */ void destroySelectActionMode(Tab tab) {
         WebContents webContents = tab.getWebContents();
         if (webContents != null) {
             SelectionPopupController.fromWebContents(webContents).destroySelectActionMode();
@@ -398,6 +423,7 @@
     @Override
     public void exitPersistentFullscreenMode() {
         if (getPersistentFullscreenMode()) {
+            cancelNotificationToast();
             mPersistentModeSupplier.set(false);
 
             if (mWebContentsInFullscreen != null && mTabInFullscreen != null) {
@@ -430,7 +456,7 @@
     }
 
     private void exitFullscreen(WebContents webContents, View contentView, Tab tab) {
-        hideNotificationToast();
+        cancelNotificationToast();
         mHandler.removeMessages(MSG_ID_SET_FULLSCREEN_SYSTEM_UI_FLAGS);
         mHandler.removeMessages(MSG_ID_CLEAR_LAYOUT_FULLSCREEN_FLAG);
 
@@ -540,6 +566,7 @@
         if (mFullscreenOnLayoutChangeListener != null) {
             contentView.removeOnLayoutChangeListener(mFullscreenOnLayoutChangeListener);
         }
+
         mFullscreenOnLayoutChangeListener = new OnLayoutChangeListener() {
             @Override
             public void onLayoutChange(View v, int left, int top, int right, int bottom,
@@ -554,10 +581,7 @@
 
                 if ((bottom - top) <= (oldBottom - oldTop)) return;
 
-                // The toast tells user how to leave fullscreen by touching the screen. Currently
-                // we do not show the toast when we're browsing in VR, since VR doesn't have
-                // touchscreen and the toast doesn't have any useful information.
-                if (shouldShowToast()) showNotificationToast();
+                beginNotificationToast();
                 contentView.removeOnLayoutChangeListener(this);
             }
         };
@@ -580,48 +604,153 @@
      * Whether we show a toast message when entering fullscreen.
      */
     private boolean shouldShowToast() {
-        return !(VrModuleProvider.getDelegate().isInVr()
-                || VrModuleProvider.getDelegate().bootsToVr());
+        // If there's no notification toast pending, such as when we're not in full screen or after
+        // we've already displayed it for longe enough, then we don't need to show the toast now.
+        if (!mIsNotificationToastPending) return false;
+
+        if (mTabInFullscreen == null) return false;
+
+        if (mTab == null) return false;
+
+        // The toast tells user how to leave fullscreen by touching the screen. Currently
+        // we do not show the toast when we're browsing in VR, since VR doesn't have
+        // touchscreen and the toast doesn't have any useful information.
+        if (VrModuleProvider.getDelegate().isInVr() || VrModuleProvider.getDelegate().bootsToVr()) {
+            return false;
+        }
+
+        final ViewGroup parent = mTab.getContentView();
+        if (parent == null) return false;
+
+        // The window must have the focus, so that it is not obscured while the notification is
+        // showing.  This also covers the case of picture in picture video, but any case of an
+        // unfocused window should prevent the toast.
+        if (!parent.hasWindowFocus()) return false;
+
+        return true;
     }
 
     /**
-     * Create and show the fullscreen notification toast.
+     * Create and show the fullscreen notification toast, if it's not already visible and if it
+     * should be visible.  It's okay to call this when it should not be; we'll do nothing.  This
+     * will fade the toast in if needed.  It will also schedule a timer to fade it back out, if it's
+     * not hidden or cancelled before then.
      */
-    private void showNotificationToast() {
+    private void createAndShowNotificationToast() {
+        // If it's already visible, then that's fine.  That includes if it's currently fading out;
+        // that's part of it.
+        if (mNotificationToast != null) return;
+
+        // If the toast should not be visible, then do nothing.
+        if (!shouldShowToast()) return;
+
         assert mTab != null && mTab.getContentView() != null;
-        ViewGroup parent = mTab.getContentView();
-        if (mNotificationToast != null) {
-            assert mToastFadeAnimation != null;
-            mToastFadeAnimation.cancel();
-            parent.removeView(mNotificationToast);
+
+        // Create a new toast and fade it in, or re-use one we've created before.
+        mNotificationToast = mActivity.getWindow().findViewById(R.id.fullscreen_notification);
+        boolean addView = false;
+        if (mNotificationToast == null) {
+            mNotificationToast =
+                    LayoutInflater.from(mActivity).inflate(R.layout.fullscreen_notification, null);
+            addView = true;
         }
-        mNotificationToast =
-                LayoutInflater.from(mActivity).inflate(R.layout.fullscreen_notification, null);
         mNotificationToast.setAlpha(0);
-        parent.addView(mNotificationToast);
         mToastFadeAnimation = mNotificationToast.animate();
-        mToastFadeAnimation.alpha(1).setDuration(TOAST_FADE_MS).start();
-        mNotificationRemainingTimeMs = 5000;
-        if (parent.hasWindowFocus()) {
-            mNotificationStartTimestamp = System.currentTimeMillis();
-            mHandler.postDelayed(mHideNotificationToastRunnable, mNotificationRemainingTimeMs);
+        if (addView) {
+            mActivity.addContentView(mNotificationToast,
+                    new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+                            ViewGroup.LayoutParams.WRAP_CONTENT));
+        } else {
+            mNotificationToast.setVisibility(View.VISIBLE);
         }
+
+        mToastFadeAnimation.alpha(1).setDuration(TOAST_FADE_MS).start();
+        mHandler.postDelayed(mFadeOutNotificationToastRunnable, TOAST_SHOW_DURATION_MS);
     }
 
     /**
-     * Hides the notification toast.
+     * Pause the notification toast, which hides it and stops all the timers.  It's okay if there is
+     * not currently a toast; we don't change any state in that case.  This will abruptly hide the
+     * toast, rather than fade it out.  This does not change `mIsNotificationToastPending`; the
+     * toast hasn't been shown long enough.
      */
-    private void hideNotificationToast() {
+    private void hideImmediatelyNotificationToast() {
         if (mNotificationToast == null) return;
+
+        // Stop the fade-out timer.
+        mHandler.removeCallbacks(mFadeOutNotificationToastRunnable);
+
+        // Remove it immediately, without fading out.
         assert mToastFadeAnimation != null;
-        mToastFadeAnimation.alpha(0).setDuration(TOAST_FADE_MS).withEndAction(() -> {
-            // The Tab might have been destroyed while the toast is on.
-            if (mTab != null && mTab.getContentView() != null) {
-                mTab.getContentView().removeView(mNotificationToast);
-            }
-            mNotificationToast = null;
-            mToastFadeAnimation = null;
-        });
+        mToastFadeAnimation.cancel();
+        mToastFadeAnimation = null;
+        // We can't actually remove it, so this will do.
+        mNotificationToast.setVisibility(View.GONE);
+        mNotificationToast = null;
+    }
+
+    /**
+     * Begin a new instance of the notification toast.  If the toast should not be shown right now,
+     * we'll start showing it when we can.
+     */
+    private void beginNotificationToast() {
+        // It would be nice if we could determine that we're not starting a new toast while a
+        // previous one is fading out.  We can't ask the animation for its current target value.  We
+        // could almost check that there's not a notification pending and also that there's no
+        // current toast.  When a notification is pending, the previous toast hasn't completed yet,
+        // so nobody should be starting a new one.  When `mNotificationToast` is not null, but
+        // pending is false, then the fade-out animation has started but not completed.  Only when
+        // they're both false is it in the steady-state of "no notification" that would let us start
+        // a new one.
+        //
+        // The problem with that is that there are cases when we double-enter fullscreen.  In
+        // particular, changing the visibility of the navigation bar and/or status bar can cause us
+        // to think that we're entering fullscreen without an intervening exit.  In this case, the
+        // right thing to do is to continue with the toast from the previous full screen, if it's
+        // still on-screen.  If it's fading out now, just let it continue to fade out.  The user has
+        // already seen it for the full duration, and we've not actually exited fullscreen.
+        if (mNotificationToast != null) {
+            // Don't reset the pending flag here -- either it's on the screen or fading out, and
+            // either way is correct.  We have not actually exited fullscreen, so we shouldn't
+            // re-display the notification.
+            return;
+        }
+
+        mIsNotificationToastPending = true;
+        createAndShowNotificationToast();
+    }
+
+    /**
+     * Cancel a toast immediately, without fading out.  For example, if we leave fullscreen, then
+     * the toast isn't needed anymore.
+     */
+    private void cancelNotificationToast() {
+        hideImmediatelyNotificationToast();
+        // Don't restart it either.
+        mIsNotificationToastPending = false;
+    }
+
+    /**
+     * Called when the notification toast should not be shown any more, because it's been on-screen
+     * long enough for the user to read it.  To re-show it, one must call `beginNotificationToast()`
+     * again.  Show / hide of the toast will no-op until then.
+     */
+    private void fadeOutNotificationToast() {
+        if (mNotificationToast == null) return;
+
+        // Clear this first, so that we know that the toast timer has expired already.
+        mIsNotificationToastPending = false;
+
+        // Cancel any timer that will start the fade-out animation, in case it's running.  It might
+        // not be, especially if we're called by it.
+        mHandler.removeCallbacks(mFadeOutNotificationToastRunnable);
+
+        // Start the fade-out animation.
+        assert mToastFadeAnimation != null;
+        mToastFadeAnimation.cancel();
+        mToastFadeAnimation.alpha(0)
+                .setDuration(TOAST_FADE_MS)
+                .withEndAction(this::hideImmediatelyNotificationToast);
     }
 
     // ActivityStateListener
@@ -653,15 +782,20 @@
     @Override
     public void onWindowFocusChanged(Activity activity, boolean hasWindowFocus) {
         if (mActivity != activity) return;
-        if (mNotificationToast != null) {
-            if (hasWindowFocus) {
-                mNotificationStartTimestamp = System.currentTimeMillis();
-                mHandler.postDelayed(mHideNotificationToastRunnable, mNotificationRemainingTimeMs);
-            } else {
-                mHandler.removeCallbacks(mHideNotificationToastRunnable);
-                mNotificationRemainingTimeMs -=
-                        System.currentTimeMillis() - mNotificationStartTimestamp;
-            }
+
+        // Try to show / hide the toast, if we need to.  Note that these won't do anything if the
+        // toast should not be visible, such as if we re-gain the window focus after having
+        // completed the most recently started notification toast.
+        //
+        // Also note that this handles picture-in-picture.  We definitely do not want the toast to
+        // be visible then; it's not relevant and also takes up almost all of the window.  We could
+        // also do this on ActivityStateChanged => PAUSED if Activity.isInPictureInPictureMode(),
+        // but it doesn't seem to be needed.
+        if (hasWindowFocus) {
+            createAndShowNotificationToast();
+        } else {
+            // While we don't have the focus, hide any ongoing notification.
+            hideImmediatelyNotificationToast();
         }
 
         mHandler.removeMessages(MSG_ID_SET_FULLSCREEN_SYSTEM_UI_FLAGS);
@@ -752,4 +886,8 @@
     void setTabForTesting(Tab tab) {
         mTab = tab;
     }
+
+    boolean isToastVisibleForTesting() {
+        return mNotificationToast != null;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
index 1d522c7f..ce7b6fc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
@@ -8,6 +8,7 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.invalidation.SessionsInvalidationManager;
@@ -34,7 +35,9 @@
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 import org.chromium.url.GURL;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Provides the domain logic and data for RecentTabsPage and RecentTabsRowAdapter.
@@ -77,6 +80,15 @@
     private final SyncService mSyncService;
 
     /**
+     * Maps Session IDs to whether that entry was restored split by entry type. These are used to
+     * record historgrams on {@link #destroy()} to measure restore ratio. Cached Session IDs are
+     * used to de-duplicate as update would otherwise result in incorrect metrics.
+     */
+    private final Map<Integer, Boolean> mTabSessionIdsRestored = new HashMap<>();
+    private final Map<Integer, Boolean> mGroupSessionIdsRestored = new HashMap<>();
+    private final Map<Integer, Boolean> mBulkSessionIdsRestored = new HashMap<>();
+
+    /**
      * Create an RecentTabsManager to be used with RecentTabsPage and RecentTabsRowAdapter.
      *
      * @param tab The Tab that is showing this recent tabs page.
@@ -120,11 +132,40 @@
         SessionsInvalidationManager.get(mProfile).onRecentTabsPageOpened();
     }
 
+    private static int countSessionIdsRestored(Map<Integer, Boolean> sessionIdToRestoredState) {
+        int count = 0;
+        for (Boolean state : sessionIdToRestoredState.values()) {
+            count += (state) ? 1 : 0;
+        }
+        return count;
+    }
+
+    private static void recordEntries(
+            String entryType, Map<Integer, Boolean> sessionIdToRestoredState) {
+        final int shownCount = sessionIdToRestoredState.size();
+        RecordHistogram.recordCount1000Histogram(
+                "Tabs.RecentlyClosed.EntriesShownInPage." + entryType, shownCount);
+        if (shownCount > 0) {
+            final int restoredCount = countSessionIdsRestored(sessionIdToRestoredState);
+            RecordHistogram.recordCount1000Histogram(
+                    "Tabs.RecentlyClosed.EntriesRestoredInPage." + entryType, restoredCount);
+            final int percentRestored = Math.round((restoredCount * 100.0f) / shownCount);
+            RecordHistogram.recordPercentageHistogram(
+                    "Tabs.RecentlyClosed.PercentOfEntriesRestoredInPage." + entryType,
+                    percentRestored);
+        }
+    }
+
     /**
      * Should be called when this object is no longer needed. Performs necessary listener tear down.
      */
     public void destroy() {
         mIsDestroyed = true;
+
+        recordEntries("Tab", mTabSessionIdsRestored);
+        recordEntries("Group", mGroupSessionIdsRestored);
+        recordEntries("Bulk", mBulkSessionIdsRestored);
+
         mSyncService.removeSyncStateChangedListener(this);
 
         mSignInManager.removeSignInStateObserver(this);
@@ -160,6 +201,18 @@
                             mRecentlyClosedTabManager.getRecentlyClosedTabs(
                                     RECENTLY_CLOSED_MAX_ENTRY_COUNT);
         }
+        for (RecentlyClosedEntry entry : mRecentlyClosedEntries) {
+            if (entry instanceof RecentlyClosedTab
+                    && !mTabSessionIdsRestored.containsKey(entry.getSessionId())) {
+                mTabSessionIdsRestored.put(entry.getSessionId(), false);
+            } else if (entry instanceof RecentlyClosedGroup
+                    && !mGroupSessionIdsRestored.containsKey(entry.getSessionId())) {
+                mGroupSessionIdsRestored.put(entry.getSessionId(), false);
+            } else if (entry instanceof RecentlyClosedBulkEvent
+                    && !mBulkSessionIdsRestored.containsKey(entry.getSessionId())) {
+                mBulkSessionIdsRestored.put(entry.getSessionId(), false);
+            }
+        }
         onUpdateDone();
     }
 
@@ -205,6 +258,7 @@
      */
     public void openRecentlyClosedTab(RecentlyClosedTab tab, int windowDisposition) {
         if (mIsDestroyed) return;
+        mTabSessionIdsRestored.put(tab.getSessionId(), true);
         RecordUserAction.record("MobileRecentTabManagerRecentTabOpened");
         // Window disposition will select which tab to open.
         mRecentlyClosedTabManager.openRecentlyClosedTab(getTabModel(), tab, windowDisposition);
@@ -217,11 +271,15 @@
      */
     public void openRecentlyClosedEntry(RecentlyClosedEntry entry) {
         if (mIsDestroyed) return;
+
         assert !(entry instanceof RecentlyClosedTab)
             : "Opening a RecentlyClosedTab should use openRecentlyClosedTab().";
+
         if (entry instanceof RecentlyClosedGroup) {
+            mGroupSessionIdsRestored.put(entry.getSessionId(), true);
             RecordUserAction.record("MobileRecentTabManagerRecentGroupOpened");
         } else if (entry instanceof RecentlyClosedBulkEvent) {
+            mBulkSessionIdsRestored.put(entry.getSessionId(), true);
             RecordUserAction.record("MobileRecentTabManagerRecentBulkEventOpened");
         }
         mRecentlyClosedTabManager.openRecentlyClosedEntry(getTabModel(), entry);
@@ -337,6 +395,7 @@
      */
     public void clearRecentlyClosedEntries() {
         if (mIsDestroyed) return;
+        RecordUserAction.record("MobileRecentTabManagerRecentTabsCleared");
         mRecentlyClosedTabManager.clearRecentlyClosedEntries();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java
index 2d10521..20e9cad6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java
@@ -4,12 +4,14 @@
 
 package org.chromium.chrome.browser.tab.tab_restore;
 
+import androidx.annotation.IntDef;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.CollectionUtil;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.NativeMethods;
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.WebContentsState;
 import org.chromium.chrome.browser.tab.WebContentsStateBridge;
@@ -20,6 +22,8 @@
 import org.chromium.content_public.common.ContentUrlConstants;
 import org.chromium.url.GURL;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -36,6 +40,18 @@
     private final TabModel mTabModel;
     private boolean mIgnoreUrlSchemesForTesting;
 
+    // These values are persisted to logs. Entries should not be renumbered and numeric values
+    // should never be reused.
+    @IntDef({HistoricalSaverCloseType.TAB, HistoricalSaverCloseType.GROUP,
+            HistoricalSaverCloseType.BULK, HistoricalSaverCloseType.COUNT})
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface HistoricalSaverCloseType {
+        int TAB = 0;
+        int GROUP = 1;
+        int BULK = 2;
+        int COUNT = 3;
+    }
+
     /**
      * @param tabModel The model from which tabs are being saved.
      */
@@ -96,18 +112,25 @@
 
         // If there is only a single entry and more than one tab remaining so this is a group.
         if (validEntries.size() == 1 && !validEntries.get(0).isSingleTab()) {
+            RecordHistogram.recordEnumeratedHistogram(
+                    "Tabs.RecentlyClosed.HistoricalSaverCloseType", HistoricalSaverCloseType.GROUP,
+                    HistoricalSaverCloseType.COUNT);
             HistoricalTabSaverImplJni.get().createHistoricalGroup(
                     mTabModel, groupTitles.get(0), allTabs.toArray(new Tab[0]));
             return;
         }
 
         // IDs are passed only to group tabs. New IDs are generated when saving.
+        RecordHistogram.recordEnumeratedHistogram("Tabs.RecentlyClosed.HistoricalSaverCloseType",
+                HistoricalSaverCloseType.BULK, HistoricalSaverCloseType.COUNT);
         HistoricalTabSaverImplJni.get().createHistoricalBulkClosure(mTabModel,
                 CollectionUtil.integerListToIntArray(groupIds), groupTitles.toArray(new String[0]),
                 CollectionUtil.integerListToIntArray(perTabGroupId), allTabs.toArray(new Tab[0]));
     }
 
     private void createHistoricalTabInternal(Tab tab) {
+        RecordHistogram.recordEnumeratedHistogram("Tabs.RecentlyClosed.HistoricalSaverCloseType",
+                HistoricalSaverCloseType.TAB, HistoricalSaverCloseType.COUNT);
         HistoricalTabSaverImplJni.get().createHistoricalTab(tab);
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditorTest.java
index 13075ae..c8edfb3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillServerCardEditorTest.java
@@ -160,7 +160,8 @@
 
         onView(withId(R.id.virtual_card_ui)).check(matches(isDisplayed()));
         onView(withId(R.id.virtual_card_enrollment_button))
-                .check(matches(withText(R.string.remove)));
+                .check(matches(withText(
+                        R.string.autofill_card_editor_virtual_card_turn_off_button_label)));
         // Ensure the activity is cleaned up.
         finishAndWaitForActivity(activity);
     }
@@ -175,7 +176,9 @@
                 fragmentArgs(SAMPLE_VIRTUAL_CARD_UNENROLLED_AND_ELIGIBLE_CARD.getGUID()));
 
         onView(withId(R.id.virtual_card_ui)).check(matches(isDisplayed()));
-        onView(withId(R.id.virtual_card_enrollment_button)).check(matches(withText(R.string.add)));
+        onView(withId(R.id.virtual_card_enrollment_button))
+                .check(matches(
+                        withText(R.string.autofill_card_editor_virtual_card_turn_on_button_label)));
         // Ensure that the native delegate is cleaned up when the test has finished.
         finishAndWaitForActivity(activity);
     }
@@ -225,7 +228,9 @@
 
         // Verify that the Virtual Card enrollment button is shown and shows "Add".
         onView(withId(R.id.virtual_card_ui)).check(matches(isDisplayed()));
-        onView(withId(R.id.virtual_card_enrollment_button)).check(matches(withText(R.string.add)));
+        onView(withId(R.id.virtual_card_enrollment_button))
+                .check(matches(
+                        withText(R.string.autofill_card_editor_virtual_card_turn_on_button_label)));
 
         // Press the Add button.
         onView(withId(R.id.virtual_card_enrollment_button)).perform(click());
@@ -239,7 +244,8 @@
         // Verify that the Virtual Card enrollment button still shows "Add" and that the button is
         // disabled.
         onView(withId(R.id.virtual_card_enrollment_button))
-                .check(matches(withText(R.string.add)))
+                .check(matches(
+                        withText(R.string.autofill_card_editor_virtual_card_turn_on_button_label)))
                 .check(matches(Matchers.not(isEnabled())));
 
         // Verify that the native enroll method was called with the correct parameters.
@@ -289,7 +295,8 @@
         // Verify that the Virtual Card enrollment button shows "Remove" and that the button is
         // enabled.
         onView(withId(R.id.virtual_card_enrollment_button))
-                .check(matches(withText(R.string.remove)))
+                .check(matches(
+                        withText(R.string.autofill_card_editor_virtual_card_turn_off_button_label)))
                 .check(matches(isEnabled()));
         // Verify that enrollment is called when the user clicks the positive button on the dialog.
         verify(mNativeMock).enrollOfferedVirtualCard(NATIVE_AUTOFILL_PAYMENTS_METHODS_DELEGATE);
@@ -311,7 +318,9 @@
 
         // Verify that the Virtual Card enrollment button is shown and shows "Add".
         onView(withId(R.id.virtual_card_ui)).check(matches(isDisplayed()));
-        onView(withId(R.id.virtual_card_enrollment_button)).check(matches(withText(R.string.add)));
+        onView(withId(R.id.virtual_card_enrollment_button))
+                .check(matches(
+                        withText(R.string.autofill_card_editor_virtual_card_turn_on_button_label)));
 
         // Press the Add button.
         onView(withId(R.id.virtual_card_enrollment_button)).perform(click());
@@ -319,7 +328,8 @@
         // Verify that the Virtual Card enrollment button still shows "Add" and that the button is
         // disabled.
         onView(withId(R.id.virtual_card_enrollment_button))
-                .check(matches(withText(R.string.add)))
+                .check(matches(
+                        withText(R.string.autofill_card_editor_virtual_card_turn_on_button_label)))
                 .check(matches(Matchers.not(isEnabled())));
 
         // Verify that the native enroll method was called with the correct parameters.
@@ -357,7 +367,8 @@
         // Verify that the Virtual Card enrollment button still shows "Add" and that the button is
         // now enabled.
         onView(withId(R.id.virtual_card_enrollment_button))
-                .check(matches(withText(R.string.add)))
+                .check(matches(
+                        withText(R.string.autofill_card_editor_virtual_card_turn_on_button_label)))
                 .check(matches(isEnabled()));
         // Verify that enrollment is called when the user clicks the positive button on the dialog.
         verify(mNativeMock, times(0))
@@ -378,7 +389,8 @@
         // Verify that the Virtual Card enrollment button is shown and shows "Remove".
         onView(withId(R.id.virtual_card_ui)).check(matches(isDisplayed()));
         onView(withId(R.id.virtual_card_enrollment_button))
-                .check(matches(withText(R.string.remove)));
+                .check(matches(withText(
+                        R.string.autofill_card_editor_virtual_card_turn_off_button_label)));
 
         // Press the Remove button.
         onView(withId(R.id.virtual_card_enrollment_button)).perform(click());
@@ -402,7 +414,8 @@
         // Verify that the Virtual Card enrollment button shows Remove.
         onView(withId(R.id.virtual_card_ui)).check(matches(isDisplayed()));
         onView(withId(R.id.virtual_card_enrollment_button))
-                .check(matches(withText(R.string.remove)));
+                .check(matches(withText(
+                        R.string.autofill_card_editor_virtual_card_turn_off_button_label)));
 
         // Press the Remove button.
         onView(withId(R.id.virtual_card_enrollment_button)).perform(click());
@@ -427,7 +440,8 @@
 
         // Verify that the button label has not changed from "Remove".
         onView(withId(R.id.virtual_card_enrollment_button))
-                .check(matches(withText(R.string.remove)));
+                .check(matches(withText(
+                        R.string.autofill_card_editor_virtual_card_turn_off_button_label)));
         // Ensure that the native delegate is cleaned up when the test has finished.
         finishAndWaitForActivity(activity);
     }
@@ -448,7 +462,8 @@
         // Verify that the Virtual Card enrollment button shows "Remove".
         onView(withId(R.id.virtual_card_ui)).check(matches(isDisplayed()));
         onView(withId(R.id.virtual_card_enrollment_button))
-                .check(matches(withText(R.string.remove)));
+                .check(matches(withText(
+                        R.string.autofill_card_editor_virtual_card_turn_off_button_label)));
 
         // Press the Remove button.
         onView(withId(R.id.virtual_card_enrollment_button)).perform(click());
@@ -466,7 +481,9 @@
                         "Autofill.VirtualCard.SettingsPageUnenrollment", /* true */ 1));
 
         // Verify that the Virtual Card enrollment button now shows "Add".
-        onView(withId(R.id.virtual_card_enrollment_button)).check(matches(withText(R.string.add)));
+        onView(withId(R.id.virtual_card_enrollment_button))
+                .check(matches(
+                        withText(R.string.autofill_card_editor_virtual_card_turn_on_button_label)));
         // Verify that the native unenroll method was called with the correct parameters.
         verify(mNativeMock).unenrollVirtualCard(NATIVE_AUTOFILL_PAYMENTS_METHODS_DELEGATE, 123);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
index 3e396293..f372bbb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
@@ -263,13 +263,17 @@
         // Android doesn't seem to like sending touch events too quickly, so have a short delay
         // between events.
         for (int i = 0; i < iterations; i++) {
-            long downTime = sendScreenTouchDown(view, x, y);
-            SystemClock.sleep(100);
-            sendScreenTouchUp(view, x, y, downTime);
-            SystemClock.sleep(100);
+            sendScreenTap(view, x, y);
         }
     }
 
+    private void sendScreenTap(final View view, final int x, final int y) {
+        long downTime = sendScreenTouchDown(view, x, y);
+        SystemClock.sleep(100);
+        sendScreenTouchUp(view, x, y, downTime);
+        SystemClock.sleep(100);
+    }
+
     /**
      * Tests that screen touches are registered as XR input in immersive sessions,
      *  when the viewer is Cardboard.
@@ -313,20 +317,20 @@
     // Note that the page should load the appropriate test page and enter any relevant session
     // before calling this.
     private void testScreenTapsRegisteredOnCardboardImpl(View presentationView, int numIterations) {
-        // Make it so that the webpage doesn't try to finish the JavaScript step after each input
-        // since we don't need to ack each one like with the Daydream controller.
-        mWebXrVrTestFramework.runJavaScriptOrFail(
-                "finishAfterEachInput = false", POLL_TIMEOUT_SHORT_MS);
         mWebXrVrTestFramework.runJavaScriptOrFail(
                 "stepSetupListeners(" + String.valueOf(numIterations) + ")", POLL_TIMEOUT_SHORT_MS);
 
         int x = presentationView.getWidth() / 2;
         int y = presentationView.getHeight() / 2;
 
-        // Tap the screen a bunch of times and make sure that they're all registered.
-        spamScreenTaps(presentationView, x, y, numIterations);
+        // Tap the screen a bunch of times and make sure that they're all registered. Ideally, we
+        // shouldn't have to ack each one, but it's possible for inputs to get eaten by garbage
+        // collection if there are multiple in flight, so only send one at a time.
+        for (int i = 0; i < numIterations; i++) {
+            sendScreenTap(presentationView, x, y);
+            mWebXrVrTestFramework.waitOnJavaScriptStep();
+        }
 
-        mWebXrVrTestFramework.waitOnJavaScriptStep();
         mWebXrVrTestFramework.endTest();
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandlerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandlerUnitTest.java
index 7b06023..d1ffd4de 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandlerUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/fullscreen/FullscreenHtmlApiHandlerUnitTest.java
@@ -10,15 +10,19 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.Activity;
+import android.view.View.OnLayoutChangeListener;
 
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
 
+import org.chromium.base.ActivityState;
 import org.chromium.base.UserDataHost;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.test.BaseRobolectricTestRunner;
@@ -27,6 +31,8 @@
 import org.chromium.chrome.browser.tab.TabAttributes;
 import org.chromium.chrome.browser.tab.TabBrowserControlsConstraintsHelper;
 import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.components.embedder_support.view.ContentView;
+import org.chromium.content_public.browser.WebContents;
 
 /**
  * Unit tests for {@link FullscreenHtmlApiHandler}.
@@ -36,7 +42,6 @@
     @Rule
     public TestRule mProcessor = new Features.JUnitProcessor();
 
-    @Mock
     private Activity mActivity;
     @Mock
     private TabAttributes mTabAttributes;
@@ -44,6 +49,10 @@
     private TabBrowserControlsConstraintsHelper mTabBrowserControlsConstraintsHelper;
     @Mock
     private Tab mTab;
+    @Mock
+    private WebContents mWebContents;
+    @Mock
+    private ContentView mContentView;
 
     private FullscreenHtmlApiHandler mFullscreenHtmlApiHandler;
     private ObservableSupplierImpl<Boolean> mAreControlsHidden;
@@ -52,12 +61,20 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mActivity = Robolectric.buildActivity(Activity.class).setup().get();
         mHost = new UserDataHost();
         doReturn(mHost).when(mTab).getUserDataHost();
 
         mAreControlsHidden = new ObservableSupplierImpl<Boolean>();
         mFullscreenHtmlApiHandler =
-                new FullscreenHtmlApiHandler(mActivity, mAreControlsHidden, false);
+                new FullscreenHtmlApiHandler(mActivity, mAreControlsHidden, false) {
+                    // This needs a PopupController, which isn't available in the test since we
+                    // can't mock statics in this version of mockito.  Even if we could mock it, it
+                    // casts to WebContentsImpl and other things that we can't reference due to
+                    // restrictions in DEPS.
+                    @Override
+                    public void destroySelectActionMode(Tab tab) {}
+                };
     }
 
     @Test
@@ -85,4 +102,56 @@
         verify(mTabBrowserControlsConstraintsHelper, times(1))
                 .update(BrowserControlsState.SHOWN, true);
     }
+
+    @Test
+    public void testToastIsShownInFullscreenButNotPictureInPicture() {
+        doReturn(mWebContents).when(mTab).getWebContents();
+        doReturn(mContentView).when(mTab).getContentView();
+        doReturn(true).when(mTab).isUserInteractable();
+        doReturn(true).when(mTab).isHidden();
+        // The window must have focus and already have the controls hidden, else fullscreen will be
+        // deferred.  The toast would be deferred with it.
+        doReturn(true).when(mContentView).hasWindowFocus();
+        mAreControlsHidden.set(true);
+
+        mFullscreenHtmlApiHandler.setTabForTesting(mTab);
+
+        FullscreenOptions fullscreenOptions = new FullscreenOptions(false, false);
+        mFullscreenHtmlApiHandler.onEnterFullscreen(mTab, fullscreenOptions);
+
+        // Catch the layout listener, which is an implementation detail but what can one do?  Note
+        // that we make the layout appear to have gotten bigger, which is important since the
+        // fullscreen handler checks for it.
+        ArgumentCaptor<OnLayoutChangeListener> arg =
+                ArgumentCaptor.forClass(OnLayoutChangeListener.class);
+        verify(mContentView).addOnLayoutChangeListener(arg.capture());
+        arg.getValue().onLayoutChange(mContentView, 0, 0, 100, 100, 0, 0, 10, 10);
+
+        // We should now be in fullscreen, with the toast shown.
+        assertTrue("Fullscreen toast should be visible in fullscreen",
+                mFullscreenHtmlApiHandler.isToastVisibleForTesting());
+
+        // Losing / gaining the focus should hide / show the toast when it's applicable.  This also
+        // covers picture in picture.
+        mFullscreenHtmlApiHandler.onWindowFocusChanged(mActivity, false);
+        assertTrue("Fullscreen toast should not be visible when unfocused",
+                !mFullscreenHtmlApiHandler.isToastVisibleForTesting());
+        mFullscreenHtmlApiHandler.onWindowFocusChanged(mActivity, true);
+        assertTrue("Fullscreen toast should be visible when focused",
+                mFullscreenHtmlApiHandler.isToastVisibleForTesting());
+
+        // Toast should not be visible when we exit fullscreen.
+        mFullscreenHtmlApiHandler.exitPersistentFullscreenMode();
+        assertTrue("Fullscreen toast should not be visible outside of fullscreen",
+                !mFullscreenHtmlApiHandler.isToastVisibleForTesting());
+
+        // If we gain / lose the focus outside of fullscreen, then nothing interesting should happen
+        // with the toast.
+        mFullscreenHtmlApiHandler.onActivityStateChange(mActivity, ActivityState.PAUSED);
+        assertTrue("Fullscreen toast should not be visible after pause",
+                !mFullscreenHtmlApiHandler.isToastVisibleForTesting());
+        mFullscreenHtmlApiHandler.onActivityStateChange(mActivity, ActivityState.RESUMED);
+        assertTrue("Fullscreen toast should not be visible after resume when not in fullscreen",
+                !mFullscreenHtmlApiHandler.isToastVisibleForTesting());
+    }
 }
diff --git a/chrome/android/modules/cablev2_authenticator/internal/BUILD.gn b/chrome/android/modules/cablev2_authenticator/internal/BUILD.gn
index 48c2015..bc16577 100644
--- a/chrome/android/modules/cablev2_authenticator/internal/BUILD.gn
+++ b/chrome/android/modules/cablev2_authenticator/internal/BUILD.gn
@@ -9,6 +9,7 @@
   sources = [ "java/src/org/chromium/chrome/modules/cablev2_authenticator/ModuleImpl.java" ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android/features/cablev2_authenticator:java",
     "//chrome/android/modules/cablev2_authenticator/public:java",
   ]
diff --git a/chrome/android/modules/dev_ui/provider/BUILD.gn b/chrome/android/modules/dev_ui/provider/BUILD.gn
index 025ee8cd..da1af52b 100644
--- a/chrome/android/modules/dev_ui/provider/BUILD.gn
+++ b/chrome/android/modules/dev_ui/provider/BUILD.gn
@@ -7,6 +7,7 @@
 android_library("java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android/features/dev_ui/public:java",
     "//components/module_installer/android:module_installer_java",
   ]
diff --git a/chrome/android/modules/stack_unwinder/internal/BUILD.gn b/chrome/android/modules/stack_unwinder/internal/BUILD.gn
index d466e5f..53d4506 100644
--- a/chrome/android/modules/stack_unwinder/internal/BUILD.gn
+++ b/chrome/android/modules/stack_unwinder/internal/BUILD.gn
@@ -10,6 +10,7 @@
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android/modules/stack_unwinder/public:java",
   ]
 }
diff --git a/chrome/android/modules/test_dummy/internal/BUILD.gn b/chrome/android/modules/test_dummy/internal/BUILD.gn
index e32169d..3bc136d 100644
--- a/chrome/android/modules/test_dummy/internal/BUILD.gn
+++ b/chrome/android/modules/test_dummy/internal/BUILD.gn
@@ -9,6 +9,7 @@
   sources = [ "java/src/org/chromium/chrome/modules/test_dummy/TestDummyProviderImpl.java" ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android/modules/test_dummy/public:java",
     "//chrome/browser/test_dummy:java",
     "//chrome/browser/test_dummy/internal:java",
diff --git a/chrome/android/webapk/libs/client/BUILD.gn b/chrome/android/webapk/libs/client/BUILD.gn
index 79770b3..adc37f5 100644
--- a/chrome/android/webapk/libs/client/BUILD.gn
+++ b/chrome/android/webapk/libs/client/BUILD.gn
@@ -31,6 +31,7 @@
     ":client_java",
     "//base:base_java",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/android/webapk/libs/common:common_java",
     "//chrome/android/webapk/libs/runtime_library:webapk_service_aidl_java",
     "//chrome/android/webapk/test:junit_test_support",
diff --git a/chrome/android/webapk/shell_apk/BUILD.gn b/chrome/android/webapk/shell_apk/BUILD.gn
index f615650..4448bc0 100644
--- a/chrome/android/webapk/shell_apk/BUILD.gn
+++ b/chrome/android/webapk/shell_apk/BUILD.gn
@@ -372,6 +372,7 @@
     ":webapk_generated_webapk_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android/webapk/libs/common:common_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_support_test_runner:runner_java",
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index fb2063d..a773920 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -2613,7 +2613,7 @@
   <message name="IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_BLOCKED_SUB_LABEL" desc="Sub label for the disabled option of the protected content content setting.">
     Media with a copyright might not play
   </message>
-  <if expr="chromeos_ash or is_win">
+  <if expr="chromeos_ash or chromeos_lacros or is_win">
     <message name="IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_IDENTIFIERS_EXPLANATION" desc="Text that is displayed on the Protected Content section of Content Settings. This text explains that enabling protected content may require using a uniquely identifiable machine identifier.">
       Sites may also need to recognize your device using an identifier
     </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index b34bc281..b6f3d09 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1064,8 +1064,6 @@
     "performance_manager/mechanisms/working_set_trimmer.h",
     "performance_manager/metrics/memory_pressure_metrics.cc",
     "performance_manager/metrics/memory_pressure_metrics.h",
-    "performance_manager/observers/isolation_context_metrics.cc",
-    "performance_manager/observers/isolation_context_metrics.h",
     "performance_manager/observers/page_load_metrics_observer.cc",
     "performance_manager/observers/page_load_metrics_observer.h",
     "performance_manager/policies/page_freezing_policy.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index abbc711..83ed56ff 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -8392,6 +8392,12 @@
      flag_descriptions::kDmTokenDeletionDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kDmTokenDeletion)},
 
+#if BUILDFLAG(IS_ANDROID)
+    {"bulk-tab-restore-android", flag_descriptions::kBulkTabRestoreAndroidName,
+     flag_descriptions::kBulkTabRestoreAndroidDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kBulkTabRestore)},
+#endif  // BUILDFLAG(IS_ANDROID)
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/browserservices/metrics/BUILD.gn b/chrome/browser/android/browserservices/metrics/BUILD.gn
index b9167c0a..faa8928d 100644
--- a/chrome/browser/android/browserservices/metrics/BUILD.gn
+++ b/chrome/browser/android/browserservices/metrics/BUILD.gn
@@ -14,6 +14,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/android/browserservices/constants:java",
     "//components/browser_ui/util/android:java",
     "//components/content_settings/android:content_settings_enums_java",
diff --git a/chrome/browser/android/browserservices/verification/BUILD.gn b/chrome/browser/android/browserservices/verification/BUILD.gn
index b32817f3..e63d1bb 100644
--- a/chrome/browser/android/browserservices/verification/BUILD.gn
+++ b/chrome/browser/android/browserservices/verification/BUILD.gn
@@ -15,6 +15,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/android/browserservices/metrics:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
diff --git a/chrome/browser/android/messages/BUILD.gn b/chrome/browser/android/messages/BUILD.gn
index a76b239..371d043 100644
--- a/chrome/browser/android/messages/BUILD.gn
+++ b/chrome/browser/android/messages/BUILD.gn
@@ -9,7 +9,10 @@
 
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 
-  deps = [ "//base:base_java" ]
+  deps = [
+    "//base:base_java",
+    "//build/android:build_java",
+  ]
 }
 
 generate_jni("jni_headers") {
diff --git a/chrome/browser/android/webapk/webapk_install_coordinator_bridge.cc b/chrome/browser/android/webapk/webapk_install_coordinator_bridge.cc
index 9ba1d0e..46e0ff1 100644
--- a/chrome/browser/android/webapk/webapk_install_coordinator_bridge.cc
+++ b/chrome/browser/android/webapk/webapk_install_coordinator_bridge.cc
@@ -11,7 +11,6 @@
 #include "base/android/jni_string.h"
 #include "base/bind.h"
 #include "base/task/bind_post_task.h"
-#include "base/task/post_task.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
diff --git a/chrome/browser/android/webapps/launchpad/BUILD.gn b/chrome/browser/android/webapps/launchpad/BUILD.gn
index b3dc6dd3..5cfad2e1 100644
--- a/chrome/browser/android/webapps/launchpad/BUILD.gn
+++ b/chrome/browser/android/webapps/launchpad/BUILD.gn
@@ -86,6 +86,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/browser/android/browserservices/intents:java",
     "//chrome/browser/profiles/android:java",
     "//chrome/test/android:chrome_java_test_support",
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
index 402fb2c..21594c2 100644
--- a/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
+++ b/chrome/browser/ash/accessibility/spoken_feedback_browsertest.cc
@@ -27,7 +27,6 @@
 #include "ash/system/unified/unified_system_tray.h"
 #include "base/bind.h"
 #include "base/command_line.h"
-#include "base/task/post_task.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "build/build_config.h"
diff --git a/chrome/browser/ash/crosapi/local_printer_ash_unittest.cc b/chrome/browser/ash/crosapi/local_printer_ash_unittest.cc
index 0fe29ea..f4437d0 100644
--- a/chrome/browser/ash/crosapi/local_printer_ash_unittest.cc
+++ b/chrome/browser/ash/crosapi/local_printer_ash_unittest.cc
@@ -230,8 +230,15 @@
 
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
     // Choose between running with local test runner or via a service.
-    feature_list_.InitWithFeatureState(features::kEnableOopPrintDrivers,
-                                       UseService());
+    if (UseService()) {
+      feature_list_.InitAndEnableFeatureWithParameters(
+          features::kEnableOopPrintDrivers,
+          {{ features::kEnableOopPrintDriversSandbox.name,
+             "true" }});
+    } else {
+      feature_list_.InitWithFeatureState(features::kEnableOopPrintDrivers,
+                                         false);
+    }
 #endif
 
     sandboxed_test_backend_ = base::MakeRefCounted<TestPrintBackend>();
diff --git a/chrome/browser/ash/crosapi/move_migrator.cc b/chrome/browser/ash/crosapi/move_migrator.cc
index 43c70e6..4a571b4a 100644
--- a/chrome/browser/ash/crosapi/move_migrator.cc
+++ b/chrome/browser/ash/crosapi/move_migrator.cc
@@ -18,7 +18,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/task/post_task.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
 #include "base/timer/elapsed_timer.h"
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
index 38b62a0..87de084 100644
--- a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
+++ b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
@@ -1075,12 +1075,13 @@
   }
 };
 
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_RegionCodeNotExistPlaceholderIsSet \
-  DISABLED_RegionCodeNotExistPlaceholderIsSet
-#else
+// TODO(crbug.com/1320444): Re-enable the test in debug.
+#if defined(NDEBUG)
 #define MAYBE_RegionCodeNotExistPlaceholderIsSet \
   RegionCodeNotExistPlaceholderIsSet
+#else
+#define MAYBE_RegionCodeNotExistPlaceholderIsSet \
+  DISABLED_RegionCodeNotExistPlaceholderIsSet
 #endif
 IN_PROC_BROWSER_TEST_F(DemoSetupRegionCodeNotExistTest,
                        MAYBE_RegionCodeNotExistPlaceholderIsSet) {
@@ -1090,6 +1091,7 @@
   enrollment_helper_.ExpectAttestationEnrollmentSuccess();
   SimulateNetworkConnected();
 
+  // TODO(crbug.com/1320412): Re-enable this test
   TriggerDemoModeOnWelcomeScreen();
 
   // Expect inactive "OK" button when entering the preference screen.
diff --git a/chrome/browser/ash/phonehub/phone_hub_manager_factory.cc b/chrome/browser/ash/phonehub/phone_hub_manager_factory.cc
index 74c702c0..65cf7e6 100644
--- a/chrome/browser/ash/phonehub/phone_hub_manager_factory.cc
+++ b/chrome/browser/ash/phonehub/phone_hub_manager_factory.cc
@@ -75,6 +75,9 @@
           "PhoneHubManager",
           BrowserContextDependencyManager::GetInstance()) {
   DependsOn(device_sync::DeviceSyncClientFactory::GetInstance());
+  if (features::IsPhoneHubCameraRollEnabled()) {
+    DependsOn(HoldingSpaceKeyedServiceFactory::GetInstance());
+  }
   DependsOn(multidevice_setup::MultiDeviceSetupClientFactory::GetInstance());
   DependsOn(secure_channel::NearbyConnectorFactory::GetInstance());
   DependsOn(SessionSyncServiceFactory::GetInstance());
diff --git a/chrome/browser/ash/platform_keys/key_permissions/key_permissions_manager_impl.cc b/chrome/browser/ash/platform_keys/key_permissions/key_permissions_manager_impl.cc
index a94d5f47..9d700ca8 100644
--- a/chrome/browser/ash/platform_keys/key_permissions/key_permissions_manager_impl.cc
+++ b/chrome/browser/ash/platform_keys/key_permissions/key_permissions_manager_impl.cc
@@ -59,11 +59,6 @@
 // update started as well as the number of times it succeeded and failed.
 const char kArcUsageUpdateStatusHistogramName[] =
     "ChromeOS.KeyPermissionsManager.ArcUsageUpdate";
-
-// The name of the histogram that records the time taken to successfully migrate
-// key permissions to chaps.
-const char kMigrationTimeHistogramName[] =
-    "ChromeOS.KeyPermissionsManager.MigrationTime";
 // The name of the histogram that records the time taken to successfully update
 // chaps with the new ARC usage flags.
 const char kArcUsageUpdateTimeHistogramName[] =
@@ -154,19 +149,6 @@
     OnUpdateFinished() {
   switch (mode_) {
     case Mode::kMigratePermissionsFromPrefs: {
-      // For more information about choosing |min| and |max| for the histogram,
-      // please refer to:
-      // https://chromium.googlesource.com/chromium/src/tools/+/refs/heads/main/metrics/histograms/README.md#count-histograms_choosing-min-and-max
-      //
-      // For more information about choosing the number of |buckets| for the
-      // histogram, please refer to:
-      // https://chromium.googlesource.com/chromium/src/tools/+/refs/heads/main/metrics/histograms/README.md#count-histograms_choosing-number-of-buckets
-      base::UmaHistogramCustomTimes(
-          kMigrationTimeHistogramName,
-          /*sample=*/base::TimeTicks::Now() - update_start_time_,
-          /*min=*/base::Milliseconds(1),
-          /*max=*/base::Minutes(5),
-          /*buckets=*/50);
       break;
     }
     case Mode::kUpdateArcUsageFlag: {
diff --git a/chrome/browser/banners/android/BUILD.gn b/chrome/browser/banners/android/BUILD.gn
index f2a987e..3fbd66e 100644
--- a/chrome/browser/banners/android/BUILD.gn
+++ b/chrome/browser/banners/android/BUILD.gn
@@ -51,6 +51,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_test_java",
     "//chrome/android:chrome_test_util_java",
diff --git a/chrome/browser/browser_controls/android/BUILD.gn b/chrome/browser/browser_controls/android/BUILD.gn
index a5be491..15f17bf0 100644
--- a/chrome/browser/browser_controls/android/BUILD.gn
+++ b/chrome/browser/browser_controls/android/BUILD.gn
@@ -34,6 +34,7 @@
     ":java",
     "//base:base_java",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//cc:cc_java",
     "//content/public/android:content_java",
     "//third_party/android_deps:robolectric_all_java",
diff --git a/chrome/browser/commerce/android/BUILD.gn b/chrome/browser/commerce/android/BUILD.gn
index 141ba13..95d0946 100644
--- a/chrome/browser/commerce/android/BUILD.gn
+++ b/chrome/browser/commerce/android/BUILD.gn
@@ -13,6 +13,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/profiles/android:java",
     "//components/commerce/core/android:core_java",
     "//components/payments/content/android:java",
diff --git a/chrome/browser/commerce/merchant_viewer/android/BUILD.gn b/chrome/browser/commerce/merchant_viewer/android/BUILD.gn
index c727748..e035042 100644
--- a/chrome/browser/commerce/merchant_viewer/android/BUILD.gn
+++ b/chrome/browser/commerce/merchant_viewer/android/BUILD.gn
@@ -32,6 +32,7 @@
   deps = [
     ":jni_headers",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android:base_module_java",
     "//chrome/android/features/tab_ui:java_resources",
     "//chrome/android/features/tab_ui:java_strings_grd",
@@ -159,6 +160,7 @@
   deps = [
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/browser/commerce/merchant_viewer:optimization_guide_protos_java",
     "//chrome/browser/commerce/merchant_viewer/android:java",
     "//chrome/browser/flags:java",
diff --git a/chrome/browser/commerce/shopping_list/android/BUILD.gn b/chrome/browser/commerce/shopping_list/android/BUILD.gn
index f6b69e9..a348b35a 100644
--- a/chrome/browser/commerce/shopping_list/android/BUILD.gn
+++ b/chrome/browser/commerce/shopping_list/android/BUILD.gn
@@ -10,6 +10,7 @@
     "//base:base_java",
     "//base:base_java",
     "//base:jni_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/power_bookmarks:proto_java",
     "//chrome/browser/profiles/android:java",
diff --git a/chrome/browser/commerce/subscriptions/android/java_sources.gni b/chrome/browser/commerce/subscriptions/android/java_sources.gni
index e56d8792..1aa0078 100644
--- a/chrome/browser/commerce/subscriptions/android/java_sources.gni
+++ b/chrome/browser/commerce/subscriptions/android/java_sources.gni
@@ -20,6 +20,7 @@
 
 commerce_subscriptions_java_deps = [
   "//base:base_java",
+  "//build/android:build_java",
   "//chrome/android:base_module_java",
   "//chrome/browser/android/lifecycle:java",
   "//chrome/browser/endpoint_fetcher:java",
diff --git a/chrome/browser/commerce/subscriptions/test/android/test_java_sources.gni b/chrome/browser/commerce/subscriptions/test/android/test_java_sources.gni
index 52dad87e..008b805 100644
--- a/chrome/browser/commerce/subscriptions/test/android/test_java_sources.gni
+++ b/chrome/browser/commerce/subscriptions/test/android/test_java_sources.gni
@@ -45,6 +45,7 @@
 commerce_subscriptions_java_test_deps = [
   "//base:base_java",
   "//base:base_java_test_support",
+  "//build/android:build_java",
   "//chrome/android:base_module_java",
   "//chrome/browser/android/lifecycle:java",
   "//chrome/browser/endpoint_fetcher:java",
diff --git a/chrome/browser/consent_auditor/android/BUILD.gn b/chrome/browser/consent_auditor/android/BUILD.gn
index 88689de..3429327f 100644
--- a/chrome/browser/consent_auditor/android/BUILD.gn
+++ b/chrome/browser/consent_auditor/android/BUILD.gn
@@ -12,6 +12,7 @@
   sources = [ "java/src/org/chromium/chrome/browser/consent_auditor/ConsentAuditorBridge.java" ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/profiles/android:java",
     "//components/signin/public/android:java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/chrome/browser/content_creation/notes/internal/android/BUILD.gn b/chrome/browser/content_creation/notes/internal/android/BUILD.gn
index 11ee6d995..b4e7c99 100644
--- a/chrome/browser/content_creation/notes/internal/android/BUILD.gn
+++ b/chrome/browser/content_creation/notes/internal/android/BUILD.gn
@@ -33,6 +33,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/content_creation/notes/android:public_java",
     "//chrome/browser/flags:java",
diff --git a/chrome/browser/content_creation/reactions/internal/android/BUILD.gn b/chrome/browser/content_creation/reactions/internal/android/BUILD.gn
index 97caff1..472074a 100644
--- a/chrome/browser/content_creation/reactions/internal/android/BUILD.gn
+++ b/chrome/browser/content_creation/reactions/internal/android/BUILD.gn
@@ -26,6 +26,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/content_creation/reactions/android:public_java",
     "//chrome/browser/flags:java",
diff --git a/chrome/browser/content_settings/content_settings_default_provider_unittest.cc b/chrome/browser/content_settings/content_settings_default_provider_unittest.cc
index b743c1c..1831cdf9 100644
--- a/chrome/browser/content_settings/content_settings_default_provider_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_default_provider_unittest.cc
@@ -174,7 +174,7 @@
   EXPECT_EQ(CONTENT_SETTING_BLOCK, prefs->GetInteger(kGeolocationPrefPath));
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
 // Tests that the protected media identifier setting is migrated.
 TEST_F(ContentSettingsDefaultProviderTest,
        MigrateProtectedMediaIdentifierPreferenceBlock) {
@@ -228,7 +228,7 @@
           website_settings->Get(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER)
               ->default_value_pref_name()));
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
 
 TEST_F(ContentSettingsDefaultProviderTest, OffTheRecord) {
   DefaultProvider otr_provider(profile_.GetPrefs(), true /* incognito */);
diff --git a/chrome/browser/contextmenu/BUILD.gn b/chrome/browser/contextmenu/BUILD.gn
index 735ad06b..d3a95bab 100644
--- a/chrome/browser/contextmenu/BUILD.gn
+++ b/chrome/browser/contextmenu/BUILD.gn
@@ -22,6 +22,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/share/android:java",
     "//components/embedder_support/android:context_menu_java",
     "//content/public/android:content_java",
diff --git a/chrome/browser/continuous_search/BUILD.gn b/chrome/browser/continuous_search/BUILD.gn
index 58b901762..4057216 100644
--- a/chrome/browser/continuous_search/BUILD.gn
+++ b/chrome/browser/continuous_search/BUILD.gn
@@ -56,6 +56,7 @@
       ":data_structures_java",
       ":java_resources",
       "//base:base_java",
+      "//build/android:build_java",
       "//chrome/browser/browser_controls/android:java",
       "//chrome/browser/continuous_search/internal:java",
       "//chrome/browser/flags:java",
@@ -135,6 +136,7 @@
       ":java",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//chrome/android:chrome_java",
       "//chrome/browser/continuous_search/internal:java",
       "//chrome/browser/flags:java",
@@ -178,6 +180,7 @@
       "//base:base_java",
       "//base:base_java_test_support",
       "//base:base_junit_test_support",
+      "//build/android:build_java",
       "//chrome/browser/browser_controls/android:java",
       "//chrome/browser/continuous_search/internal:java",
       "//chrome/browser/flags:java",
diff --git a/chrome/browser/continuous_search/internal/BUILD.gn b/chrome/browser/continuous_search/internal/BUILD.gn
index a9fa9b6..4f4ce50 100644
--- a/chrome/browser/continuous_search/internal/BUILD.gn
+++ b/chrome/browser/continuous_search/internal/BUILD.gn
@@ -30,6 +30,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android:chrome_app_java_resources",
     "//chrome/browser/continuous_search:data_structures_java",
     "//chrome/browser/flags:java",
diff --git a/chrome/browser/device/BUILD.gn b/chrome/browser/device/BUILD.gn
index 72aed64f..920b4e5 100644
--- a/chrome/browser/device/BUILD.gn
+++ b/chrome/browser/device/BUILD.gn
@@ -34,6 +34,7 @@
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//chrome/test/android:chrome_java_test_support",
     "//net/android:net_java",
     "//third_party/android_deps:robolectric_all_java",
diff --git a/chrome/browser/device_reauth/android/BUILD.gn b/chrome/browser/device_reauth/android/BUILD.gn
index 25e8c8b7..80c15acf 100644
--- a/chrome/browser/device_reauth/android/BUILD.gn
+++ b/chrome/browser/device_reauth/android/BUILD.gn
@@ -8,6 +8,7 @@
 android_library("java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/ui/android/strings:ui_strings_grd",
     "//components/browser_ui/strings/android:browser_ui_strings_grd",
     "//components/device_reauth:device_reauth_java_enums",
diff --git a/chrome/browser/dips/cookie_access_filter.h b/chrome/browser/dips/cookie_access_filter.h
index 2e64a43..8fc2c6c 100644
--- a/chrome/browser/dips/cookie_access_filter.h
+++ b/chrome/browser/dips/cookie_access_filter.h
@@ -31,6 +31,9 @@
   [[nodiscard]] bool Filter(const std::vector<GURL>& urls,
                             std::vector<size_t>* result) const;
 
+  // Returns true iff AddAccess() has never been called.
+  bool is_empty() const { return accesses_.empty(); }
+
  private:
   struct CookieAccess {
     GURL url;
diff --git a/chrome/browser/dips/dips_bounce_detector.cc b/chrome/browser/dips/dips_bounce_detector.cc
index ea8d87d..59f9095 100644
--- a/chrome/browser/dips/dips_bounce_detector.cc
+++ b/chrome/browser/dips/dips_bounce_detector.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "chrome/browser/dips/cookie_access_filter.h"
+#include "components/site_engagement/content/site_engagement_service.h"
 #include "content/public/browser/cookie_access_details.h"
 #include "content/public/browser/navigation_handle.h"
 
@@ -15,11 +16,13 @@
 namespace {
 
 // BounceDetectionState gets attached to NavigationHandle (which is a
-// SupportsUserData subclass) to store which URLs accessed cookies (since
-// WebContentsObserver::OnCookiesAccessed is called in an unpredictable order
-// with respect to WCO::DidRedirectNavigation).
+// SupportsUserData subclass) to store data needed to detect stateful server
+// redirects.
 class BounceDetectionState : public base::SupportsUserData::Data {
  public:
+  // The WebContents' previously committed URL at the time the navigation
+  // started. Needed in case a parallel navigation commits.
+  GURL initial_url;
   CookieAccessFilter filter;
 };
 
@@ -30,6 +33,12 @@
 DIPSBounceDetector::DIPSBounceDetector(content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
       content::WebContentsUserData<DIPSBounceDetector>(*web_contents),
+      site_engagement_service_(site_engagement::SiteEngagementService::Get(
+          web_contents->GetBrowserContext())),
+      // It's safe to use unretained because the callback is owned by this.
+      stateful_server_redirect_handler_(
+          base::BindRepeating(&DIPSBounceDetector::HandleStatefulServerRedirect,
+                              base::Unretained(this))),
       // It's safe to use unretained because the callback is owned by this.
       stateful_redirect_handler_(
           base::BindRepeating(&DIPSBounceDetector::HandleStatefulRedirect,
@@ -37,10 +46,36 @@
 
 DIPSBounceDetector::~DIPSBounceDetector() = default;
 
-void DIPSBounceDetector::HandleStatefulRedirect(
+void DIPSBounceDetector::HandleStatefulRedirect(const GURL& prev_url,
+                                                const GURL& url,
+                                                const GURL& next_url) {
+  double score = site_engagement_service_->GetScore(url);
+  (void)score;
+  // TODO: fire UKM metric
+}
+
+void DIPSBounceDetector::HandleStatefulServerRedirect(
+    const GURL& prev_url,
     content::NavigationHandle* navigation_handle,
     int redirect_index) {
-  // TODO: fire UKM metric
+  const auto& redirect_chain = navigation_handle->GetRedirectChain();
+  const GURL& url = redirect_chain[redirect_index];
+  // We are called from DidFinishNavigation() so GetURL() returns the final URL.
+  // XXX For 204 No Content responses, should we actually use `prev_url`, since
+  // it's what the user actually sees?
+  const GURL& next_url = navigation_handle->GetURL();
+  stateful_redirect_handler_.Run(prev_url, url, next_url);
+}
+
+void DIPSBounceDetector::DidStartNavigation(
+    NavigationHandle* navigation_handle) {
+  if (!navigation_handle->IsInPrimaryMainFrame()) {
+    return;
+  }
+
+  auto state = std::make_unique<BounceDetectionState>();
+  state->initial_url = web_contents()->GetLastCommittedURL();
+  navigation_handle->SetUserData(kBounceDetectionStateKey, std::move(state));
 }
 
 void DIPSBounceDetector::OnCookiesAccessed(
@@ -50,17 +85,11 @@
     return;
   }
 
-  auto* existing_state = static_cast<BounceDetectionState*>(
+  auto* state = static_cast<BounceDetectionState*>(
       navigation_handle->GetUserData(kBounceDetectionStateKey));
-  if (existing_state) {
-    existing_state->filter.AddAccess(details.url, details.type);
-    return;
+  if (state) {
+    state->filter.AddAccess(details.url, details.type);
   }
-
-  auto new_state = std::make_unique<BounceDetectionState>();
-  new_state->filter.AddAccess(details.url, details.type);
-  navigation_handle->SetUserData(kBounceDetectionStateKey,
-                                 std::move(new_state));
 }
 
 void DIPSBounceDetector::DidFinishNavigation(
@@ -73,7 +102,7 @@
   // point.
   auto* state = static_cast<BounceDetectionState*>(
       navigation_handle->GetUserData(kBounceDetectionStateKey));
-  if (state) {
+  if (state && !state->filter.is_empty()) {
     std::vector<size_t> accessor_idxs;
     if (!state->filter.Filter(navigation_handle->GetRedirectChain(),
                               &accessor_idxs)) {
@@ -87,7 +116,8 @@
         // redirect.
         continue;
       }
-      stateful_redirect_handler_.Run(navigation_handle, accessor_idx);
+      stateful_server_redirect_handler_.Run(state->initial_url,
+                                            navigation_handle, accessor_idx);
     }
   }
 }
diff --git a/chrome/browser/dips/dips_bounce_detector.h b/chrome/browser/dips/dips_bounce_detector.h
index be4df451..6cc8d119 100644
--- a/chrome/browser/dips/dips_bounce_detector.h
+++ b/chrome/browser/dips/dips_bounce_detector.h
@@ -6,9 +6,14 @@
 #define CHROME_BROWSER_DIPS_DIPS_BOUNCE_DETECTOR_H_
 
 #include "base/callback.h"
+#include "base/memory/raw_ptr.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 
+namespace site_engagement {
+class SiteEngagementService;
+}
+
 class DIPSBounceDetector
     : public content::WebContentsObserver,
       public content::WebContentsUserData<DIPSBounceDetector> {
@@ -17,8 +22,16 @@
   DIPSBounceDetector(const DIPSBounceDetector&) = delete;
   DIPSBounceDetector& operator=(const DIPSBounceDetector&) = delete;
 
+  using ServerRedirectHandler = base::RepeatingCallback<
+      void(const GURL&, content::NavigationHandle*, int)>;
+
   using RedirectHandler =
-      base::RepeatingCallback<void(content::NavigationHandle*, int)>;
+      base::RepeatingCallback<void(const GURL&, const GURL&, const GURL&)>;
+
+  void SetStatefulServerRedirectHandlerForTesting(
+      ServerRedirectHandler handler) {
+    stateful_server_redirect_handler_ = handler;
+  }
 
   void SetStatefulRedirectHandlerForTesting(RedirectHandler handler) {
     stateful_redirect_handler_ = handler;
@@ -29,15 +42,32 @@
   // So WebContentsUserData::CreateForWebContents() can call the constructor.
   friend class content::WebContentsUserData<DIPSBounceDetector>;
 
-  void HandleStatefulRedirect(content::NavigationHandle*, int);
+  // Called when any stateful redirect is detected.
+  //
+  // `prev_url` is the page previously committed before starting the chain of
+  // redirects. `url` is the redirect URL itself (possibly one of many).
+  // `next_url` is the final URL after the chain of redirects completes.
+  void HandleStatefulRedirect(const GURL& prev_url,
+                              const GURL& url,
+                              const GURL& next_url);
+  void HandleStatefulServerRedirect(
+      const GURL& prev_url,
+      content::NavigationHandle* navigation_handle,
+      int redirect_index);
 
+  void DidStartNavigation(
+      content::NavigationHandle* navigation_handle) override;
   void OnCookiesAccessed(content::NavigationHandle* navigation_handle,
                          const content::CookieAccessDetails& details) override;
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
 
-  // By default, this just calls this->HandleStatefulRedirect(), but it can be
-  // overridden for tests.
+  raw_ptr<site_engagement::SiteEngagementService> site_engagement_service_;
+  // By default, this just calls this->HandleStatefulServerRedirect(), but it
+  // can be overridden for tests.
+  ServerRedirectHandler stateful_server_redirect_handler_;
+  // By default, this just calls this->HandleStatefulRedirect(), but it
+  // can be overridden for tests.
   RedirectHandler stateful_redirect_handler_;
 
   WEB_CONTENTS_USER_DATA_KEY_DECL();
diff --git a/chrome/browser/dips/dips_bounce_detector_browsertest.cc b/chrome/browser/dips/dips_bounce_detector_browsertest.cc
index 7fd2e5c..31ab1a3 100644
--- a/chrome/browser/dips/dips_bounce_detector_browsertest.cc
+++ b/chrome/browser/dips/dips_bounce_detector_browsertest.cc
@@ -181,12 +181,14 @@
 }
 
 void AppendRedirectURL(std::vector<std::string>* urls,
+                       const GURL& prev_url,
                        NavigationHandle* navigation_handle,
                        int i) {
   urls->push_back(FormatURL(navigation_handle->GetRedirectChain()[i]));
 }
 
-IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest, DetectStatefulBounces) {
+IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
+                       DetectStatefulServerRedirect) {
   GURL redirect_url = embedded_test_server()->GetURL(
       "a.test",
       "/cross-site-with-cookie/b.test/cross-site/c.test/cross-site/d.test/"
@@ -206,7 +208,7 @@
       embedded_test_server()->GetURL("d.test", "/set-cookie?name=value")));
 
   std::vector<std::string> stateful_redirects;
-  bounce_detector()->SetStatefulRedirectHandlerForTesting(
+  bounce_detector()->SetStatefulServerRedirectHandlerForTesting(
       base::BindRepeating(&AppendRedirectURL, &stateful_redirects));
 
   // Visit the redirect.
@@ -276,7 +278,7 @@
   content::WebContents* web_contents = GetActiveWebContents();
 
   std::vector<std::string> stateful_redirects;
-  bounce_detector()->SetStatefulRedirectHandlerForTesting(
+  bounce_detector()->SetStatefulServerRedirectHandlerForTesting(
       base::BindRepeating(&AppendRedirectURL, &stateful_redirects));
 
   ASSERT_TRUE(content::NavigateToURL(web_contents, root_url));
@@ -287,3 +289,137 @@
   // it.
   EXPECT_THAT(stateful_redirects, testing::IsEmpty());
 }
+
+void AppendRedirect(std::vector<std::string>* redirects,
+                    const GURL& prev_url,
+                    const GURL& url,
+                    const GURL& next_url) {
+  redirects->push_back(
+      base::StrCat({FormatURL(prev_url), " -> ", FormatURL(url), " -> ",
+                    FormatURL(next_url)}));
+}
+
+IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
+                       DetectStatefulRedirect_Server) {
+  GURL initial_url = embedded_test_server()->GetURL("a.test", "/title1.html");
+  GURL redirect_url = embedded_test_server()->GetURL(
+      "a.test",
+      "/cross-site-with-cookie/b.test/cross-site/c.test/cross-site/d.test/"
+      "title1.html");
+  GURL final_url = embedded_test_server()->GetURL("d.test", "/title1.html");
+  content::WebContents* web_contents = GetActiveWebContents();
+
+  // Set cookies on a.test, b.test and d.test (but not c.test).
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents,
+      embedded_test_server()->GetURL("a.test", "/set-cookie?name=value")));
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents,
+      embedded_test_server()->GetURL("b.test", "/set-cookie?name=value")));
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents,
+      embedded_test_server()->GetURL("d.test", "/set-cookie?name=value")));
+
+  std::vector<std::string> redirects;
+  bounce_detector()->SetStatefulRedirectHandlerForTesting(
+      base::BindRepeating(&AppendRedirect, &redirects));
+
+  ASSERT_TRUE(content::NavigateToURL(web_contents, initial_url));
+  // Visit the redirect.
+  ASSERT_TRUE(content::NavigateToURL(web_contents, redirect_url, final_url));
+
+  // a.test and b.test are stateful redirects. c.test had no cookies, and d.test
+  // was not a redirect.
+  EXPECT_THAT(redirects,
+              testing::ElementsAre(
+                  ("a.test/title1.html -> "
+                   "a.test/cross-site-with-cookie/b.test/cross-site/c.test/"
+                   "cross-site/d.test/title1.html -> d.test/title1.html"),
+                  ("a.test/title1.html -> "
+                   "b.test/cross-site/c.test/cross-site/d.test/title1.html -> "
+                   "d.test/title1.html")));
+}
+
+IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
+                       DetectStatefulRedirect_NoContent) {
+  GURL initial_url = embedded_test_server()->GetURL("a.test", "/title1.html");
+  // The redirect chain ends in a 204 No Content response, which doesn't commit.
+  GURL redirect_url = embedded_test_server()->GetURL(
+      "a.test",
+      "/cross-site-with-cookie/b.test/cross-site/c.test/cross-site/d.test/"
+      "nocontent");
+  content::WebContents* web_contents = GetActiveWebContents();
+
+  // Set cookies on a.test, b.test and d.test (but not c.test).
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents,
+      embedded_test_server()->GetURL("a.test", "/set-cookie?name=value")));
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents,
+      embedded_test_server()->GetURL("b.test", "/set-cookie?name=value")));
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents,
+      embedded_test_server()->GetURL("d.test", "/set-cookie?name=value")));
+
+  std::vector<std::string> redirects;
+  bounce_detector()->SetStatefulRedirectHandlerForTesting(
+      base::BindRepeating(&AppendRedirect, &redirects));
+
+  ASSERT_TRUE(content::NavigateToURL(web_contents, initial_url));
+  // Visit the redirect (note that the user ends up back at initial_url).
+  ASSERT_TRUE(content::NavigateToURL(web_contents, redirect_url,
+                                     /*expected_commit_url=*/initial_url));
+
+  // a.test and b.test are stateful redirects. c.test had no cookies, and d.test
+  // was not a redirect.
+  EXPECT_THAT(redirects,
+              testing::ElementsAre(
+                  ("a.test/title1.html -> "
+                   "a.test/cross-site-with-cookie/b.test/cross-site/c.test/"
+                   "cross-site/d.test/nocontent -> d.test/nocontent"),
+                  ("a.test/title1.html -> "
+                   "b.test/cross-site/c.test/cross-site/d.test/nocontent -> "
+                   "d.test/nocontent")));
+}
+
+IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest,
+                       DetectStatefulRedirect_404Error) {
+  GURL initial_url = embedded_test_server()->GetURL("a.test", "/title1.html");
+  // The redirect chain ends in a 404 error.
+  GURL redirect_url = embedded_test_server()->GetURL(
+      "a.test",
+      "/cross-site-with-cookie/b.test/cross-site/c.test/cross-site/d.test/404");
+  content::WebContents* web_contents = GetActiveWebContents();
+
+  // Set cookies on a.test, b.test and d.test (but not c.test).
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents,
+      embedded_test_server()->GetURL("a.test", "/set-cookie?name=value")));
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents,
+      embedded_test_server()->GetURL("b.test", "/set-cookie?name=value")));
+  ASSERT_TRUE(content::NavigateToURL(
+      web_contents,
+      embedded_test_server()->GetURL("d.test", "/set-cookie?name=value")));
+
+  std::vector<std::string> redirects;
+  bounce_detector()->SetStatefulRedirectHandlerForTesting(
+      base::BindRepeating(&AppendRedirect, &redirects));
+
+  ASSERT_TRUE(content::NavigateToURL(web_contents, initial_url));
+  // Visit the redirect, ending up on an error page.
+  ASSERT_FALSE(content::NavigateToURL(web_contents, redirect_url));
+  ASSERT_TRUE(content::IsLastCommittedEntryOfPageType(
+      web_contents, content::PAGE_TYPE_ERROR));
+
+  // a.test and b.test are stateful redirects. c.test had no cookies, and d.test
+  // was not a redirect.
+  EXPECT_THAT(redirects,
+              testing::ElementsAre(
+                  ("a.test/title1.html -> "
+                   "a.test/cross-site-with-cookie/b.test/cross-site/c.test/"
+                   "cross-site/d.test/404 -> d.test/404"),
+                  ("a.test/title1.html -> "
+                   "b.test/cross-site/c.test/cross-site/d.test/404 -> "
+                   "d.test/404")));
+}
diff --git a/chrome/browser/download/android/BUILD.gn b/chrome/browser/download/android/BUILD.gn
index a9940f2e..6967ba9 100644
--- a/chrome/browser/download/android/BUILD.gn
+++ b/chrome/browser/download/android/BUILD.gn
@@ -78,6 +78,7 @@
     ":file_provider_java",
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/offline_pages/android:java",
     "//chrome/browser/preferences:java",
@@ -166,6 +167,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
@@ -208,6 +210,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
     "//chrome/test/android:chrome_java_test_support",
diff --git a/chrome/browser/download/internal/android/BUILD.gn b/chrome/browser/download/internal/android/BUILD.gn
index b93a617..ab4f60b9 100644
--- a/chrome/browser/download/internal/android/BUILD.gn
+++ b/chrome/browser/download/internal/android/BUILD.gn
@@ -109,6 +109,7 @@
     ":java_resources",
     ":jni_headers",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/download/android:file_provider_java",
     "//chrome/browser/download/android:java",
     "//chrome/browser/preferences:java",
@@ -286,6 +287,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/browser/download/android:java",
     "//chrome/browser/profiles/android:java",
     "//components/browser_ui/util/android:java",
diff --git a/chrome/browser/endpoint_fetcher/BUILD.gn b/chrome/browser/endpoint_fetcher/BUILD.gn
index 2cb20bb9..3b49d0c 100644
--- a/chrome/browser/endpoint_fetcher/BUILD.gn
+++ b/chrome/browser/endpoint_fetcher/BUILD.gn
@@ -8,6 +8,7 @@
   deps = [
     ":jni_headers",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/profiles/android:java",
     "//net/android:net_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/chrome/browser/enterprise/util/BUILD.gn b/chrome/browser/enterprise/util/BUILD.gn
index 0321d7f..a172972 100644
--- a/chrome/browser/enterprise/util/BUILD.gn
+++ b/chrome/browser/enterprise/util/BUILD.gn
@@ -13,6 +13,7 @@
   sources = _jni_sources
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/profiles/android:java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc
index 6ab7e04e..edf18c4d 100644
--- a/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc
+++ b/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc
@@ -39,8 +39,8 @@
     const base::Value& value,
     std::string* error) {
   scoped_refptr<url_matcher::URLMatcherConditionSet> url_matcher_condition_set;
-  const base::DictionaryValue* dict = nullptr;
-  if (!value.GetAsDictionary(&dict)) {
+  const base::Value::Dict* dict = value.GetIfDict();
+  if (!dict) {
     *error = base::StringPrintf(kPageUrlInvalidTypeOfParameter,
                                 declarative_content_constants::kPageUrl);
     return nullptr;
@@ -48,7 +48,7 @@
 
   url_matcher_condition_set =
       url_matcher::URLMatcherFactory::CreateFromURLFilterDictionary(
-          url_matcher_condition_factory, dict, ++g_next_id, error);
+          url_matcher_condition_factory, *dict, ++g_next_id, error);
   if (!url_matcher_condition_set)
     return nullptr;
   return base::WrapUnique(new DeclarativeContentPageUrlPredicate(
diff --git a/chrome/browser/feature_engagement/BUILD.gn b/chrome/browser/feature_engagement/BUILD.gn
index 616b883..5efde7b 100644
--- a/chrome/browser/feature_engagement/BUILD.gn
+++ b/chrome/browser/feature_engagement/BUILD.gn
@@ -15,6 +15,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/tab:java",
     "//components/feature_engagement/public:public_java",
diff --git a/chrome/browser/feed/android/BUILD.gn b/chrome/browser/feed/android/BUILD.gn
index 3da209b4..2dae34d 100644
--- a/chrome/browser/feed/android/BUILD.gn
+++ b/chrome/browser/feed/android/BUILD.gn
@@ -86,6 +86,7 @@
   deps = [
     ":feed_java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android:base_module_java",
     "//chrome/browser/browser_controls/android:java",
     "//chrome/browser/feature_engagement:java",
@@ -310,6 +311,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/browser/feature_engagement:java",
     "//chrome/browser/feedback/android:java",
     "//chrome/browser/flags:java",
diff --git a/chrome/browser/feedback/android/BUILD.gn b/chrome/browser/feedback/android/BUILD.gn
index 360953e..91a7409 100644
--- a/chrome/browser/feedback/android/BUILD.gn
+++ b/chrome/browser/feedback/android/BUILD.gn
@@ -51,6 +51,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/profiles/android:java",
     "//components/browser_ui/util/android:java",
     "//components/variations/android:variations_java",
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 1d67de5..2ed4301 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -670,6 +670,11 @@
     "expiry_milestone": 106
   },
   {
+    "name": "bulk-tab-restore-android",
+    "owners": ["ckitagawa", "fredmello"],
+    "expiry_milestone": 110
+  },
+  {
     "name": "bypass-app-banner-engagement-checks",
     "owners": [ "dmurph" ],
     "expiry_milestone": 95
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 96bdafc..fc3ef201 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2981,6 +2981,11 @@
 const char kBackGestureRefactorAndroidDescription[] =
     "Enable Back Gesture Refactor.";
 
+const char kBulkTabRestoreAndroidName[] = "Recent Tabs Bulk Restore";
+const char kBulkTabRestoreAndroidDescription[] =
+    "Enables restoration of bulk tab closures (e.g. close all tabs, close "
+    "a group, etc.) from Recent Tabs > Recently Closed.";
+
 const char kCCTIncognitoName[] = "Chrome Custom Tabs Incognito mode";
 const char kCCTIncognitoDescription[] =
     "Enables incognito mode for Chrome Custom Tabs, on Android.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index dd3f32f8..f45281d 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1681,6 +1681,9 @@
 extern const char kBackGestureRefactorAndroidName[];
 extern const char kBackGestureRefactorAndroidDescription[];
 
+extern const char kBulkTabRestoreAndroidName[];
+extern const char kBulkTabRestoreAndroidDescription[];
+
 extern const char kCCTIncognitoName[];
 extern const char kCCTIncognitoDescription[];
 
diff --git a/chrome/browser/flags/BUILD.gn b/chrome/browser/flags/BUILD.gn
index 2be51b1..8a98e1b 100644
--- a/chrome/browser/flags/BUILD.gn
+++ b/chrome/browser/flags/BUILD.gn
@@ -23,6 +23,7 @@
   deps = [
     "//base:base_java",
     "//build:chromeos_buildflags",
+    "//build/android:build_java",
     "//chrome/browser/preferences:java",
     "//components/version_info/android:version_constants_java",
     "//third_party/android_deps:guava_android_java",
@@ -104,6 +105,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//chrome/test/android:chrome_java_test_support",
     "//third_party/android_sdk:android_test_mock_java",
     "//third_party/android_support_test_runner:runner_java",
diff --git a/chrome/browser/history_clusters/BUILD.gn b/chrome/browser/history_clusters/BUILD.gn
index 06f0c36d8..c356003 100644
--- a/chrome/browser/history_clusters/BUILD.gn
+++ b/chrome/browser/history_clusters/BUILD.gn
@@ -31,6 +31,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/ui/android/favicon:java",
     "//components/browser_ui/widget/android:java",
diff --git a/chrome/browser/image_descriptions/BUILD.gn b/chrome/browser/image_descriptions/BUILD.gn
index a2722d10..a7620de 100644
--- a/chrome/browser/image_descriptions/BUILD.gn
+++ b/chrome/browser/image_descriptions/BUILD.gn
@@ -16,6 +16,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/device:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
diff --git a/chrome/browser/incognito/BUILD.gn b/chrome/browser/incognito/BUILD.gn
index cdd0f000..8950e12 100644
--- a/chrome/browser/incognito/BUILD.gn
+++ b/chrome/browser/incognito/BUILD.gn
@@ -25,6 +25,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/android/lifecycle:java",
     "//chrome/browser/dependency_injection:java",
     "//chrome/browser/device_reauth/android:java",
diff --git a/chrome/browser/language/android/BUILD.gn b/chrome/browser/language/android/BUILD.gn
index c99cca8..35a5c34 100644
--- a/chrome/browser/language/android/BUILD.gn
+++ b/chrome/browser/language/android/BUILD.gn
@@ -46,6 +46,7 @@
     ":base_module_java",
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
diff --git a/chrome/browser/locale/BUILD.gn b/chrome/browser/locale/BUILD.gn
index 8630691..082e3ec5 100644
--- a/chrome/browser/locale/BUILD.gn
+++ b/chrome/browser/locale/BUILD.gn
@@ -75,6 +75,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/chrome/browser/notifications/BUILD.gn b/chrome/browser/notifications/BUILD.gn
index 8adb53a3..8b48e1e 100644
--- a/chrome/browser/notifications/BUILD.gn
+++ b/chrome/browser/notifications/BUILD.gn
@@ -120,6 +120,7 @@
       "//base:base_java",
       "//base:base_java_test_support",
       "//base:base_junit_test_support",
+      "//build/android:build_java",
       "//chrome/browser/flags:java",
       "//chrome/browser/preferences:java",
       "//chrome/test/android:chrome_java_test_support",
@@ -155,6 +156,7 @@
       ":java",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//chrome/browser/flags:java",
       "//chrome/browser/preferences:java",
       "//chrome/test/android:chrome_java_test_support",
diff --git a/chrome/browser/offline_pages/android/BUILD.gn b/chrome/browser/offline_pages/android/BUILD.gn
index 32ea448..47232fd 100644
--- a/chrome/browser/offline_pages/android/BUILD.gn
+++ b/chrome/browser/offline_pages/android/BUILD.gn
@@ -9,6 +9,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/profiles/android:java",
   ]
diff --git a/chrome/browser/optimization_guide/android/BUILD.gn b/chrome/browser/optimization_guide/android/BUILD.gn
index 01c22b1..22a37f8 100644
--- a/chrome/browser/optimization_guide/android/BUILD.gn
+++ b/chrome/browser/optimization_guide/android/BUILD.gn
@@ -17,6 +17,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
@@ -78,6 +79,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_test_util_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
diff --git a/chrome/browser/page_annotations/android/BUILD.gn b/chrome/browser/page_annotations/android/BUILD.gn
index e569c92..ef0ecb782 100644
--- a/chrome/browser/page_annotations/android/BUILD.gn
+++ b/chrome/browser/page_annotations/android/BUILD.gn
@@ -19,6 +19,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/endpoint_fetcher:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/profiles/android:java",
diff --git a/chrome/browser/page_annotations/test/android/BUILD.gn b/chrome/browser/page_annotations/test/android/BUILD.gn
index a9acfbe..000ebaa 100644
--- a/chrome/browser/page_annotations/test/android/BUILD.gn
+++ b/chrome/browser/page_annotations/test/android/BUILD.gn
@@ -46,6 +46,7 @@
   deps = [
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/browser/endpoint_fetcher:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/page_annotations/android:java",
diff --git a/chrome/browser/paint_preview/android/BUILD.gn b/chrome/browser/paint_preview/android/BUILD.gn
index 371189af..3d06d5d 100644
--- a/chrome/browser/paint_preview/android/BUILD.gn
+++ b/chrome/browser/paint_preview/android/BUILD.gn
@@ -28,6 +28,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/android/lifecycle:java",
     "//chrome/browser/browser_controls/android:java",
     "//chrome/browser/flags:java",
@@ -36,6 +37,7 @@
     "//chrome/browser/ui/messages/android:java",
     "//chrome/browser/util:java",
     "//components/browser_ui/styles/android:java",
+    "//components/embedder_support/android:util_java",
     "//components/paint_preview/browser/android:java",
     "//components/paint_preview/player/android:java",
     "//content/public/android:content_java",
diff --git a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabService.java b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabService.java
index 7a30dfb..e8c8315 100644
--- a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabService.java
+++ b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabService.java
@@ -14,10 +14,13 @@
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.task.PostTask;
+import org.chromium.chrome.browser.flags.BooleanCachedFieldTrialParameter;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
+import org.chromium.components.embedder_support.util.UrlUtilitiesJni;
 import org.chromium.components.paintpreview.browser.NativePaintPreviewServiceProvider;
 import org.chromium.content_public.browser.RenderCoordinates;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
@@ -33,6 +36,10 @@
  */
 @JNINamespace("paint_preview")
 public class PaintPreviewTabService implements NativePaintPreviewServiceProvider {
+    public static final BooleanCachedFieldTrialParameter ALLOW_SRP =
+            new BooleanCachedFieldTrialParameter(
+                    ChromeFeatureList.PAINT_PREVIEW_SHOW_ON_STARTUP, "allow_srp", true);
+
     private static final long AUDIT_START_DELAY_MS = 2 * 60 * 1000; // Two minutes;
     private static boolean sIsAccessibilityEnabledForTesting;
 
@@ -86,7 +93,14 @@
             String scheme = tab.getUrl().getScheme();
             boolean schemeAllowed = scheme.equals("http") || scheme.equals("https");
             return !tab.isIncognito() && !tab.isNativePage() && !tab.isShowingErrorPage()
-                    && tab.getWebContents() != null && !tab.isLoading() && schemeAllowed;
+                    && tab.getWebContents() != null && !tab.isLoading() && schemeAllowed
+                    && allowIfSrp(tab);
+        }
+
+        private boolean allowIfSrp(Tab tab) {
+            if (ALLOW_SRP.getValue()) return true;
+
+            return !UrlUtilitiesJni.get().isGoogleSearchUrl(tab.getUrl().getSpec());
         }
     }
 
diff --git a/chrome/browser/partnerbookmarks/BUILD.gn b/chrome/browser/partnerbookmarks/BUILD.gn
index 2c81259..ce1e8c2 100644
--- a/chrome/browser/partnerbookmarks/BUILD.gn
+++ b/chrome/browser/partnerbookmarks/BUILD.gn
@@ -18,6 +18,7 @@
   deps = [
     "//base:base_java",
     "//base:jni_java",
+    "//build/android:build_java",
     "//chrome/browser/partnercustomizations:java",
     "//components/embedder_support/android:util_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/chrome/browser/partnercustomizations/BUILD.gn b/chrome/browser/partnercustomizations/BUILD.gn
index 26cc6dcd7..7e05a65 100644
--- a/chrome/browser/partnercustomizations/BUILD.gn
+++ b/chrome/browser/partnercustomizations/BUILD.gn
@@ -52,6 +52,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/test/android:chrome_java_test_support",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_support_test_runner:runner_java",
@@ -73,6 +74,7 @@
     ":test_support_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/test/android:chrome_java_test_support",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_support_test_runner:runner_java",
diff --git a/chrome/browser/password_check/android/BUILD.gn b/chrome/browser/password_check/android/BUILD.gn
index 984fa24d..b59952c 100644
--- a/chrome/browser/password_check/android/BUILD.gn
+++ b/chrome/browser/password_check/android/BUILD.gn
@@ -90,6 +90,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/browser/device_reauth/android:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/password_check/android:password_check_java_enums",
@@ -123,6 +124,7 @@
     "internal:internal_ui_factory_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_test_java",
     "//chrome/android:chrome_test_util_java",
diff --git a/chrome/browser/password_check/android/internal/BUILD.gn b/chrome/browser/password_check/android/internal/BUILD.gn
index 7523790..dffd3c7 100644
--- a/chrome/browser/password_check/android/internal/BUILD.gn
+++ b/chrome/browser/password_check/android/internal/BUILD.gn
@@ -69,6 +69,7 @@
     ":java_resources",
     ":public_factory_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android:chrome_app_java_resources",
     "//chrome/browser/device_reauth/android:java",
     "//chrome/browser/feedback/android:java",
diff --git a/chrome/browser/password_entry_edit/android/internal/BUILD.gn b/chrome/browser/password_entry_edit/android/internal/BUILD.gn
index ad46c13..2641416 100644
--- a/chrome/browser/password_entry_edit/android/internal/BUILD.gn
+++ b/chrome/browser/password_entry_edit/android/internal/BUILD.gn
@@ -23,6 +23,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/feedback/android:java",
     "//chrome/browser/password_entry_edit/android:java",
     "//chrome/browser/password_manager/android:java",
diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/password_manager/android/BUILD.gn
index eef364cf..ad7ecb2 100644
--- a/chrome/browser/password_manager/android/BUILD.gn
+++ b/chrome/browser/password_manager/android/BUILD.gn
@@ -67,6 +67,7 @@
     ":settings_interface_java",
     "$google_play_services_package:google_play_services_basement_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/device_reauth/android:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/profiles/android:java",
diff --git a/chrome/browser/payments/android/BUILD.gn b/chrome/browser/payments/android/BUILD.gn
index bff639a..86ee060 100644
--- a/chrome/browser/payments/android/BUILD.gn
+++ b/chrome/browser/payments/android/BUILD.gn
@@ -19,6 +19,7 @@
   testonly = true
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/android/lifecycle:java",
     "//chrome/browser/profiles/android:java",
@@ -56,6 +57,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/profiles/android:java",
     "//components/payments/content/android:java",
diff --git a/chrome/browser/performance_hints/android/BUILD.gn b/chrome/browser/performance_hints/android/BUILD.gn
index 30b3b86..3fbaabe4 100644
--- a/chrome/browser/performance_hints/android/BUILD.gn
+++ b/chrome/browser/performance_hints/android/BUILD.gn
@@ -13,6 +13,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//url:gurl_java",
diff --git a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
index b12bae8..ced1cfd3 100644
--- a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
+++ b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/performance_manager/decorators/helpers/page_live_state_decorator_helper.h"
 #include "chrome/browser/performance_manager/decorators/page_aggregator.h"
 #include "chrome/browser/performance_manager/metrics/memory_pressure_metrics.h"
-#include "chrome/browser/performance_manager/observers/isolation_context_metrics.h"
 #include "chrome/browser/performance_manager/observers/page_load_metrics_observer.h"
 #include "chrome/browser/performance_manager/policies/background_tab_loading_policy.h"
 #include "chrome/browser/performance_manager/policies/high_pmf_discard_policy.h"
@@ -83,8 +82,6 @@
   graph->PassToGraph(
       std::make_unique<performance_manager::FrozenFrameAggregator>());
   graph->PassToGraph(
-      std::make_unique<performance_manager::IsolationContextMetrics>());
-  graph->PassToGraph(
       std::make_unique<performance_manager::ProcessMetricsDecorator>());
 
   if (performance_manager::policies::WorkingSetTrimmerPolicy::
diff --git a/chrome/browser/performance_manager/observers/isolation_context_metrics.cc b/chrome/browser/performance_manager/observers/isolation_context_metrics.cc
deleted file mode 100644
index 7e58698..0000000
--- a/chrome/browser/performance_manager/observers/isolation_context_metrics.cc
+++ /dev/null
@@ -1,283 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/performance_manager/observers/isolation_context_metrics.h"
-
-#include <cmath>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/metrics/histogram_macros.h"
-#include "components/performance_manager/public/graph/node_attached_data.h"
-
-namespace performance_manager {
-
-namespace {
-
-// Given |data|, an instance of DataType that contains a |last_reported| field,
-// calculates and returns the amount of time (in seconds) that has elapsed since
-// the last report was filed, and updates the last report time to |now|.
-template <typename DataType>
-int GetSecondsSinceLastReportAndUpdate(const base::TimeTicks now,
-                                       const base::TimeDelta reporting_interval,
-                                       DataType* data) {
-  auto elapsed = now - data->last_reported;
-  data->last_reported = now;
-
-  // It's entirely possible for time to advance by extremely large jumps if the
-  // machine is put to sleep, for example. In this case, the data won't
-  // meaningfully contribute to metrics. If the amount of time elapsed greatly
-  // surpasses our reporting interval, silently drop the report by returning
-  // that no time has elapsed.
-  if (elapsed >= 2 * reporting_interval)
-    return 0;
-
-  return static_cast<int>(std::round(elapsed.InSecondsF()));
-}
-
-// Adds |count| samples of the given |value| to the linear histogram with the
-// provided |name|. Assumes the enum starts at 0, and ends at
-// EnumType::kMaxValue inclusively. This is templated on the histogram name so
-// that each histogram gets a distinct static histogram pointer.
-template <const char* kName, typename EnumType>
-void AddCountsToHistogram(EnumType value, int count) {
-  static constexpr int32_t kMaxValue =
-      static_cast<int32_t>(EnumType::kMaxValue);
-  STATIC_HISTOGRAM_POINTER_BLOCK(
-      kName, AddCount(static_cast<int32_t>(value), count),
-      base::LinearHistogram::FactoryGet(
-          kName, 0, kMaxValue, kMaxValue + 1,
-          base::HistogramBase::kUmaTargetedHistogramFlag));
-}
-
-}  // namespace
-
-// Wrapper around ProcessData providing storage. Keeps the impl details out of
-// the header.
-struct IsolationContextMetricsProcessDataImpl
-    : public ExternalNodeAttachedDataImpl<
-          IsolationContextMetricsProcessDataImpl> {
-  explicit IsolationContextMetricsProcessDataImpl(
-      const ProcessNode* process_node) {}
-
-  IsolationContextMetricsProcessDataImpl(
-      const IsolationContextMetricsProcessDataImpl&) = delete;
-  IsolationContextMetricsProcessDataImpl& operator=(
-      const IsolationContextMetricsProcessDataImpl&) = delete;
-
-  ~IsolationContextMetricsProcessDataImpl() override = default;
-
-  IsolationContextMetrics::ProcessData process_data;
-};
-
-// static
-constexpr base::TimeDelta IsolationContextMetrics::kReportingInterval;
-
-// static
-const char IsolationContextMetrics::kProcessDataByTimeHistogramName[] =
-    "PerformanceManager.FrameSiteInstanceProcessRelationship.ByTime2";
-
-// static
-const char IsolationContextMetrics::kProcessDataByProcessHistogramName[] =
-    "PerformanceManager.FrameSiteInstanceProcessRelationship.ByProcess2";
-
-// static
-const char IsolationContextMetrics::kFramesPerRendererByTimeHistogram[] =
-    "PerformanceManager.FramesPerRendererByTime";
-
-// static
-const char IsolationContextMetrics::kSiteInstancesPerRendererByTimeHistogram[] =
-    "PerformanceManager.SiteInstancesPerRendererByTime";
-
-IsolationContextMetrics::IsolationContextMetrics() = default;
-
-IsolationContextMetrics::~IsolationContextMetrics() {}
-
-void IsolationContextMetrics::StartTimer() {
-  // The timer cancels itself when it goes out of scope, so base::Unretained is
-  // safe here.
-  reporting_timer_.Start(
-      FROM_HERE, kReportingInterval,
-      base::BindRepeating(&IsolationContextMetrics::OnReportingTimerFired,
-                          base::Unretained(this)));
-}
-
-void IsolationContextMetrics::OnFrameNodeAdded(const FrameNode* frame_node) {
-  // Track frame node births and use that to keep ProcessData up to date.
-  ChangeFrameCount(frame_node, 1);
-
-  // This should be impossible, as frame nodes are created not current, and
-  // are added to the graph before |IsCurrent| is set.
-  DCHECK(!frame_node->IsCurrent());
-}
-
-void IsolationContextMetrics::OnBeforeFrameNodeRemoved(
-    const FrameNode* frame_node) {
-  // Track frame node deaths and use that to keep ProcessData up to date.
-  ChangeFrameCount(frame_node, -1);
-}
-
-void IsolationContextMetrics::OnPassedToGraph(Graph* graph) {
-  graph_ = graph;
-  RegisterObservers(graph);
-}
-
-void IsolationContextMetrics::OnTakenFromGraph(Graph* graph) {
-  UnregisterObservers(graph);
-  graph_ = nullptr;
-}
-
-void IsolationContextMetrics::OnBeforeProcessNodeRemoved(
-    const ProcessNode* process_node) {
-  // Track process death and use that to report whether or not the process
-  // ever hosted frames from the same site instance. The ProcessData will only
-  // exist for renderer processes that ever actually hosted frames.
-  if (auto* process_data = ProcessData::Get(process_node)) {
-    auto state = ProcessDataState::kOnlyOneFrameExists;
-    if (process_data->has_hosted_multiple_frames) {
-      state = process_data->has_hosted_multiple_frames_with_same_site_instance
-                  ? ProcessDataState::kSomeFramesHaveSameSiteInstance
-                  : ProcessDataState::kAllFramesHaveDistinctSiteInstances;
-    }
-    UMA_HISTOGRAM_ENUMERATION(kProcessDataByProcessHistogramName, state);
-  }
-}
-
-void IsolationContextMetrics::RegisterObservers(Graph* graph) {
-  graph->AddFrameNodeObserver(this);
-  graph->AddProcessNodeObserver(this);
-  StartTimer();
-}
-
-void IsolationContextMetrics::UnregisterObservers(Graph* graph) {
-  graph->RemoveFrameNodeObserver(this);
-  graph->RemoveProcessNodeObserver(this);
-
-  // Drain all metrics on shutdown to avoid losing the tail.
-  reporting_timer_.Stop();
-  OnReportingTimerFired();
-}
-
-// static
-IsolationContextMetrics::ProcessDataState
-IsolationContextMetrics::GetProcessDataState(const ProcessData* process_data) {
-  if (process_data->site_instance_frame_count.empty())
-    return ProcessDataState::kUndefined;
-
-  if (process_data->multi_frame_site_instance_count == 0) {
-    if (process_data->site_instance_frame_count.size() == 1)
-      return ProcessDataState::kOnlyOneFrameExists;
-    return ProcessDataState::kAllFramesHaveDistinctSiteInstances;
-  }
-
-  return ProcessDataState::kSomeFramesHaveSameSiteInstance;
-}
-
-// static
-void IsolationContextMetrics::ReportProcessData(ProcessData* process_data,
-                                                ProcessDataState state,
-                                                base::TimeTicks now) {
-  const int seconds =
-      GetSecondsSinceLastReportAndUpdate(now, kReportingInterval, process_data);
-  if (seconds) {
-    AddCountsToHistogram<kProcessDataByTimeHistogramName>(state, seconds);
-
-    // The following are effectively UMA_HISTOGRAM_COUNTS_100, but using
-    // AddCount rather than Add.
-    STATIC_HISTOGRAM_POINTER_BLOCK(
-        kFramesPerRendererByTimeHistogram,
-        AddCount(process_data->frame_count, seconds),
-        base::Histogram::FactoryGet(
-            kFramesPerRendererByTimeHistogram, 1, 100, 50,
-            base::HistogramBase::kUmaTargetedHistogramFlag));
-
-    STATIC_HISTOGRAM_POINTER_BLOCK(
-        kSiteInstancesPerRendererByTimeHistogram,
-        AddCount(process_data->site_instance_frame_count.size(), seconds),
-        base::Histogram::FactoryGet(
-            kSiteInstancesPerRendererByTimeHistogram, 1, 100, 50,
-            base::HistogramBase::kUmaTargetedHistogramFlag));
-  }
-}
-
-void IsolationContextMetrics::ReportAllProcessData(base::TimeTicks now) {
-  for (const auto* process_node : graph_->GetAllProcessNodes()) {
-    auto* process_data = ProcessData::Get(process_node);
-    if (process_data)
-      ReportProcessData(process_data, GetProcessDataState(process_data), now);
-  }
-}
-
-void IsolationContextMetrics::ChangeFrameCount(const FrameNode* frame_node,
-                                               int delta) {
-  DCHECK(delta == -1 || delta == 1);
-  const auto* process_node = frame_node->GetProcessNode();
-  auto* data = ProcessData::GetOrCreate(process_node);
-  const auto old_state = GetProcessDataState(data);
-
-  if (delta == 1) {
-    if (++data->frame_count > 1)
-      data->has_hosted_multiple_frames = true;
-  } else {
-    --data->frame_count;
-  }
-
-  auto iter = data->site_instance_frame_count
-                  .insert(std::make_pair(frame_node->GetSiteInstanceId(), 0))
-                  .first;
-
-  DCHECK_LE(0, iter->second);
-  const int frame_count = iter->second += delta;
-  DCHECK_LE(0, iter->second);
-
-  if (delta == 1 && frame_count == 2) {
-    ++data->multi_frame_site_instance_count;
-    data->has_hosted_multiple_frames_with_same_site_instance = true;
-  } else if (delta == -1 && frame_count == 1) {
-    --data->multi_frame_site_instance_count;
-  }
-
-  if (frame_count == 0)
-    data->site_instance_frame_count.erase(iter);
-
-  const auto new_state = GetProcessDataState(data);
-
-  if (old_state == ProcessDataState::kUndefined || old_state == new_state)
-    return;
-
-  // Report the state change. Flush all other related data so as not to
-  // introduce bias into the metrics when only a partial reporting cycle occurs.
-  const auto now = base::TimeTicks::Now();
-  ReportProcessData(data, old_state, now);
-  ReportAllProcessData(now);
-}
-
-void IsolationContextMetrics::OnReportingTimerFired() {
-  const auto now = base::TimeTicks::Now();
-  ReportAllProcessData(now);
-}
-
-IsolationContextMetrics::ProcessData::ProcessData()
-    : last_reported(base::TimeTicks::Now()) {}
-
-IsolationContextMetrics::ProcessData::~ProcessData() = default;
-
-// static
-IsolationContextMetrics::ProcessData* IsolationContextMetrics::ProcessData::Get(
-    const ProcessNode* process_node) {
-  auto* impl = IsolationContextMetricsProcessDataImpl::Get(process_node);
-  if (!impl)
-    return nullptr;
-  return &impl->process_data;
-}
-
-// static
-IsolationContextMetrics::ProcessData*
-IsolationContextMetrics::ProcessData::GetOrCreate(
-    const ProcessNode* process_node) {
-  return &IsolationContextMetricsProcessDataImpl::GetOrCreate(process_node)
-              ->process_data;
-}
-
-}  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/observers/isolation_context_metrics.h b/chrome/browser/performance_manager/observers/isolation_context_metrics.h
deleted file mode 100644
index 45ddbdc..0000000
--- a/chrome/browser/performance_manager/observers/isolation_context_metrics.h
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_ISOLATION_CONTEXT_METRICS_H_
-#define CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_ISOLATION_CONTEXT_METRICS_H_
-
-#include <unordered_map>
-
-#include "base/containers/small_map.h"
-#include "base/memory/raw_ptr.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "components/performance_manager/public/graph/frame_node.h"
-#include "components/performance_manager/public/graph/graph.h"
-#include "components/performance_manager/public/graph/process_node.h"
-#include "content/public/browser/site_instance.h"
-
-namespace performance_manager {
-
-// A graph observer that tracks various metrics related to the isolation context
-// of frames and pages:
-//
-// (1) How common it is for frames to be hosted in a same process that don't
-//     actually need to be hosted together (they are not in the same site
-//     instance and thus can't synchronously script each other). This is to
-//     inform value of work on Blink Isolates.
-// (2) How common it is for pages to be in browsing instances with other pages,
-//     as opposed to in browsing instances on their own. This is for estimating
-//     the impact of extending freezing logic to entire browsing instances.
-class IsolationContextMetrics : public FrameNode::ObserverDefaultImpl,
-                                public GraphOwned,
-                                public ProcessNode::ObserverDefaultImpl {
- public:
-  IsolationContextMetrics();
-
-  IsolationContextMetrics(const IsolationContextMetrics&) = delete;
-  IsolationContextMetrics& operator=(const IsolationContextMetrics&) = delete;
-
-  ~IsolationContextMetrics() override;
-
-  // Starts the timer for periodic reporting.
-  void StartTimer();
-
- protected:
-  // Helper struct that implements storage for ProcessData.
-  friend struct IsolationContextMetricsProcessDataImpl;
-
-  // Periodic reporting interval. This would ideally be triggered by UMA
-  // collection and not on its own timer, but UMA collection lives on the UI
-  // thread. This wants to be something on the same order of magnitude as UMA
-  // collection but not so fast as to cause pointless wakeups.
-  static constexpr base::TimeDelta kReportingInterval = base::Minutes(5);
-
-  // This histogram records the cumulative amount of time a process spends
-  // hosting only frames from distinct site instances, versus hosting more than
-  // one frame from the same site instance. See ProcessDataState for details.
-  static const char kProcessDataByTimeHistogramName[];
-  // This histogram records the number of processes that ever only host frames
-  // from distinct site instances, versus those that ever host more than one
-  // frame from the same site instance. See ProcessDataState for details.
-  static const char kProcessDataByProcessHistogramName[];
-  // This histogram records the number of frames in a renderer over time.
-  static const char kFramesPerRendererByTimeHistogram[];
-  // This histogram records the number of site instances in a renderer over
-  // time.
-  static const char kSiteInstancesPerRendererByTimeHistogram[];
-
-  // Tracks the number of distinct site instances being hosted per process.
-  struct ProcessData {
-    ProcessData();
-    ~ProcessData();
-
-    // Factories/accessors for node attached data.
-    static ProcessData* Get(const ProcessNode* process_node);
-    static ProcessData* GetOrCreate(const ProcessNode* process_node);
-
-    // A map between site instance ID and the number of frames with that site
-    // instance in the process. This is typically small for most processes, but
-    // can go to O(100s) for power users hence the use of small_map.
-    base::small_map<
-        std::unordered_map<content::SiteInstanceId,
-                           int,
-                           typename content::SiteInstanceId::Hasher>>
-        site_instance_frame_count;
-    // The number of frames in this process.
-    int frame_count = 0;
-    // The number of site instances with multiple frames in this process.
-    // Basically, this counts the number of entries in
-    // |site_instance_frame_count| that are > 1.
-    int multi_frame_site_instance_count = 0;
-    // Whether or not this process has *ever* hosted multiple frames.
-    bool has_hosted_multiple_frames = false;
-    // Whether or not this process has *ever* hosted multiple frames in the same
-    // site instance. This goes to true if |multi_frame_site_instance_count| is
-    // ever greater than 0.
-    bool has_hosted_multiple_frames_with_same_site_instance = false;
-    // The last time data related to this process was reported to the histogram.
-    // This happens on a timer or on state changes. This is initialized to the
-    // time of the struct creation.
-    base::TimeTicks last_reported;
-  };
-
-  // A state that can be calculated from a ProcessData.
-  enum class ProcessDataState {
-    kUndefined = -1,  // This value is never reported, but used in logic.
-    kAllFramesHaveDistinctSiteInstances = 0,
-    kSomeFramesHaveSameSiteInstance = 1,
-    kOnlyOneFrameExists = 2,
-    // Must be maintained as the max value.
-    kMaxValue = kOnlyOneFrameExists
-  };
-
-  // FrameNodeObserver implementation:
-  void OnFrameNodeAdded(const FrameNode* frame_node) override;
-  void OnBeforeFrameNodeRemoved(const FrameNode* frame_node) override;
-
-  // GraphOwned implementation:
-  void OnPassedToGraph(Graph* graph) override;
-  void OnTakenFromGraph(Graph* graph) override;
-
-  // ProcessNodeObserver implementation:
-  void OnBeforeProcessNodeRemoved(const ProcessNode* process_node) override;
-
-  // (Un)registers the various node observer flavors of this object with the
-  // graph. These are invoked by OnPassedToGraph and OnTakenFromGraph, but
-  // hoisted to their own functions for testing.
-  void RegisterObservers(Graph* graph);
-  void UnregisterObservers(Graph* graph);
-
-  // Returns the state associated with a ProcessData.
-  static ProcessDataState GetProcessDataState(const ProcessData* process_data);
-
-  // Reports data associated with a ProcessData.
-  static void ReportProcessData(ProcessData* process_data,
-                                ProcessDataState state,
-                                base::TimeTicks now);
-
-  // Reports all process data.
-  void ReportAllProcessData(base::TimeTicks now);
-
-  // Adds or removes a frame from the relevant process data. The |delta| should
-  // be +/- 1.
-  void ChangeFrameCount(const FrameNode* frame_node, int delta);
-
-  // This is virtual in order to provide a testing seam.
-  virtual void OnReportingTimerFired();
-
-  // The graph to which this object belongs.
-  raw_ptr<Graph> graph_ = nullptr;
-
-  // Timer that is used to periodically flush metrics. This ensures that they
-  // are mostly up to date in the event of a catastrophic browser crash. We
-  // could do this on the same schedule as UMA itself by being a MetricsProvider
-  // but that is UI thread bound, and would require all sorts of hassles for us
-  // to build.
-  // TODO(chrisha): Migrate away if metrics team provides a convenient API.
-  // https://crbug.com/961468
-  base::RepeatingTimer reporting_timer_;
-};
-
-}  // namespace performance_manager
-
-#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_OBSERVERS_ISOLATION_CONTEXT_METRICS_H_
diff --git a/chrome/browser/performance_manager/observers/isolation_context_metrics_unittest.cc b/chrome/browser/performance_manager/observers/isolation_context_metrics_unittest.cc
deleted file mode 100644
index 33ca171..0000000
--- a/chrome/browser/performance_manager/observers/isolation_context_metrics_unittest.cc
+++ /dev/null
@@ -1,391 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/performance_manager/observers/isolation_context_metrics.h"
-
-#include "base/callback.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/raw_ptr.h"
-#include "base/run_loop.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "components/performance_manager/graph/frame_node_impl.h"
-#include "components/performance_manager/graph/page_node_impl.h"
-#include "components/performance_manager/graph/process_node_impl.h"
-#include "components/performance_manager/test_support/graph_test_harness.h"
-
-namespace performance_manager {
-
-class TestIsolationContextMetrics : public IsolationContextMetrics {
- public:
-  TestIsolationContextMetrics() = default;
-  ~TestIsolationContextMetrics() override = default;
-
-  void OnReportingTimerFired() override {
-    IsolationContextMetrics::OnReportingTimerFired();
-    if (on_reporting_timer_fired_closure_)
-      on_reporting_timer_fired_closure_.Run();
-  }
-
-  // Expose some things for testing.
-  using IsolationContextMetrics::GetProcessDataState;
-  using IsolationContextMetrics::kFramesPerRendererByTimeHistogram;
-  using IsolationContextMetrics::kProcessDataByProcessHistogramName;
-  using IsolationContextMetrics::kProcessDataByTimeHistogramName;
-  using IsolationContextMetrics::kReportingInterval;
-  using IsolationContextMetrics::kSiteInstancesPerRendererByTimeHistogram;
-  using IsolationContextMetrics::ProcessData;
-  using IsolationContextMetrics::ProcessDataState;
-
-  // This closure will be invoked when OnReportingTimerFired. Allows the timer
-  // to be exercised under tests.
-  base::RepeatingClosure on_reporting_timer_fired_closure_;
-};
-
-class IsolationContextMetricsTest : public GraphTestHarness {
- public:
-  using Super = GraphTestHarness;
-
-  IsolationContextMetricsTest()
-      : GraphTestHarness(
-            base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED,
-            base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
-
-  ~IsolationContextMetricsTest() override = default;
-
-  // Bring some types into the namespace for convenience.
-  using ProcessData = TestIsolationContextMetrics::ProcessData;
-  using ProcessDataState = TestIsolationContextMetrics::ProcessDataState;
-
-  // Browsing instance IDs.
-  static constexpr int32_t kBID1 = 1;
-  static constexpr int32_t kBID2 = 2;
-  static constexpr int32_t kBID3 = 3;
-
-  // Site instance IDs.
-  static constexpr int32_t kSID1 = 1;
-  static constexpr int32_t kSID2 = 2;
-  static constexpr int32_t kSID3 = 3;
-
-  void SetUp() override {
-    Super::SetUp();
-    metrics_ = new TestIsolationContextMetrics();
-
-    // Sets a valid starting time.
-    AdvanceClock(base::Seconds(1));
-    graph()->PassToGraph(base::WrapUnique(metrics_.get()));
-  }
-
-  // A frame node constructor that lets us specify the browsing instance ID and
-  // site instance ID, but defaults everything else.
-  TestNodeWrapper<FrameNodeImpl> CreateFrameNode(
-      ProcessNodeImpl* process_node,
-      PageNodeImpl* page_node,
-      int32_t browsing_instance_id,
-      int32_t site_instance_id,
-      FrameNodeImpl* parent_frame_node = nullptr) {
-    return CreateNode<FrameNodeImpl>(
-        process_node, page_node, parent_frame_node, ++next_render_frame_id_,
-        blink::LocalFrameToken(),
-        content::BrowsingInstanceId(browsing_instance_id),
-        content::SiteInstanceId(site_instance_id));
-  }
-
-  // Advance time until the timer fires.
-  void FastForwardUntilTimerFires() {
-    base::RunLoop run_loop;
-    metrics_->on_reporting_timer_fired_closure_ = run_loop.QuitClosure();
-    run_loop.Run();
-    metrics_->on_reporting_timer_fired_closure_ = base::RepeatingClosure();
-  }
-
-  base::HistogramTester histogram_tester_;
-  raw_ptr<TestIsolationContextMetrics> metrics_;
-  int next_render_frame_id_ = 0;
-};
-
-// static
-constexpr int32_t IsolationContextMetricsTest::kBID1;
-constexpr int32_t IsolationContextMetricsTest::kBID2;
-constexpr int32_t IsolationContextMetricsTest::kBID3;
-constexpr int32_t IsolationContextMetricsTest::kSID1;
-constexpr int32_t IsolationContextMetricsTest::kSID2;
-constexpr int32_t IsolationContextMetricsTest::kSID3;
-
-TEST_F(IsolationContextMetricsTest, GetProcessDataState) {
-  TestIsolationContextMetrics::ProcessData data;
-  EXPECT_TRUE(data.site_instance_frame_count.empty());
-  EXPECT_EQ(0, data.multi_frame_site_instance_count);
-  EXPECT_FALSE(data.has_hosted_multiple_frames_with_same_site_instance);
-  EXPECT_EQ(task_env().NowTicks(), data.last_reported);
-
-  EXPECT_EQ(ProcessDataState::kUndefined,
-            TestIsolationContextMetrics::GetProcessDataState(&data));
-
-  // Make up a site instance with one frame.
-  data.site_instance_frame_count[content::SiteInstanceId(kSID1)] = 1;
-  EXPECT_EQ(1u, data.site_instance_frame_count.size());
-  EXPECT_EQ(ProcessDataState::kOnlyOneFrameExists,
-            TestIsolationContextMetrics::GetProcessDataState(&data));
-
-  // Make up another site instance with one frame.
-  data.site_instance_frame_count[content::SiteInstanceId(kSID2)] = 1;
-  EXPECT_EQ(2u, data.site_instance_frame_count.size());
-  EXPECT_EQ(ProcessDataState::kAllFramesHaveDistinctSiteInstances,
-            TestIsolationContextMetrics::GetProcessDataState(&data));
-
-  // Make one site instance have multiple frames.
-  data.site_instance_frame_count[content::SiteInstanceId(kSID1)] = 2;
-  data.multi_frame_site_instance_count = 1;
-  data.has_hosted_multiple_frames_with_same_site_instance = true;
-  EXPECT_EQ(2u, data.site_instance_frame_count.size());
-  EXPECT_EQ(ProcessDataState::kSomeFramesHaveSameSiteInstance,
-            TestIsolationContextMetrics::GetProcessDataState(&data));
-
-  // Make the second site instance have multiple frames.
-  data.site_instance_frame_count[content::SiteInstanceId(kSID2)] = 2;
-  data.multi_frame_site_instance_count = 2;
-  EXPECT_EQ(2u, data.site_instance_frame_count.size());
-  EXPECT_EQ(ProcessDataState::kSomeFramesHaveSameSiteInstance,
-            TestIsolationContextMetrics::GetProcessDataState(&data));
-
-  // Reduce the first site instance to 1 frame.
-  data.site_instance_frame_count[content::SiteInstanceId(kSID1)] = 1;
-  data.multi_frame_site_instance_count = 1;
-  EXPECT_EQ(2u, data.site_instance_frame_count.size());
-  EXPECT_EQ(ProcessDataState::kSomeFramesHaveSameSiteInstance,
-            TestIsolationContextMetrics::GetProcessDataState(&data));
-
-  // And reduce the second site instance to 1 frame.
-  data.site_instance_frame_count[content::SiteInstanceId(kSID2)] = 1;
-  data.multi_frame_site_instance_count = 0;
-  EXPECT_EQ(2u, data.site_instance_frame_count.size());
-  EXPECT_EQ(ProcessDataState::kAllFramesHaveDistinctSiteInstances,
-            TestIsolationContextMetrics::GetProcessDataState(&data));
-
-  // Erase the first site instance.
-  data.site_instance_frame_count.erase(content::SiteInstanceId(kSID1));
-  EXPECT_EQ(1u, data.site_instance_frame_count.size());
-  EXPECT_EQ(ProcessDataState::kOnlyOneFrameExists,
-            TestIsolationContextMetrics::GetProcessDataState(&data));
-}
-
-TEST_F(IsolationContextMetricsTest, ProcessDataReporting) {
-  metrics_->StartTimer();
-
-  // Create a process that never hosts any frames. It should never contribute
-  // at all to the metrics.
-  auto empty_process = CreateNode<ProcessNodeImpl>();
-
-  // Create a process that hosts 1 frame from 1 page.
-  auto process = CreateNode<ProcessNodeImpl>();
-  auto page = CreateNode<PageNodeImpl>();
-  auto frame1 = CreateFrameNode(process.get(), page.get(), kBID1, kSID1);
-
-  // Expect the ProcessData to exist and be correctly filled out.
-  auto* data1 = ProcessData::GetOrCreate(process.get());
-  EXPECT_EQ(1u, data1->site_instance_frame_count.size());
-  EXPECT_EQ(1, data1->frame_count);
-  EXPECT_EQ(0, data1->multi_frame_site_instance_count);
-  EXPECT_FALSE(data1->has_hosted_multiple_frames);
-  EXPECT_FALSE(data1->has_hosted_multiple_frames_with_same_site_instance);
-  EXPECT_EQ(task_env().NowTicks(), data1->last_reported);
-  EXPECT_EQ(ProcessDataState::kOnlyOneFrameExists,
-            TestIsolationContextMetrics::GetProcessDataState(data1));
-
-  // Expect no metrics to have been emitted.
-  histogram_tester_.ExpectTotalCount(metrics_->kProcessDataByTimeHistogramName,
-                                     0);
-  histogram_tester_.ExpectTotalCount(
-      metrics_->kProcessDataByProcessHistogramName, 0);
-  histogram_tester_.ExpectTotalCount(
-      metrics_->kFramesPerRendererByTimeHistogram, 0);
-  histogram_tester_.ExpectTotalCount(
-      metrics_->kSiteInstancesPerRendererByTimeHistogram, 0);
-
-  FastForwardUntilTimerFires();
-
-  // Expect "by time" metrics to have been emitted.
-  EXPECT_EQ(task_env().NowTicks(), data1->last_reported);
-  histogram_tester_.ExpectUniqueSample(
-      metrics_->kProcessDataByTimeHistogramName,
-      ProcessDataState::kOnlyOneFrameExists,
-      metrics_->kReportingInterval.InSeconds());
-  histogram_tester_.ExpectTotalCount(
-      metrics_->kProcessDataByProcessHistogramName, 0);
-  histogram_tester_.ExpectUniqueSample(
-      metrics_->kFramesPerRendererByTimeHistogram, 1,
-      metrics_->kReportingInterval.InSeconds());
-  histogram_tester_.ExpectUniqueSample(
-      metrics_->kSiteInstancesPerRendererByTimeHistogram, 1,
-      metrics_->kReportingInterval.InSeconds());
-
-  {
-    // Advance time and add another frame to a new site instance, as a child
-    // of |frame1|.
-    AdvanceClock(base::Seconds(1));
-    auto frame2 =
-        CreateFrameNode(process.get(), page.get(), kBID1, kSID2, frame1.get());
-    EXPECT_EQ(2u, data1->site_instance_frame_count.size());
-    EXPECT_EQ(2, data1->frame_count);
-    EXPECT_EQ(0, data1->multi_frame_site_instance_count);
-    EXPECT_TRUE(data1->has_hosted_multiple_frames);
-    EXPECT_FALSE(data1->has_hosted_multiple_frames_with_same_site_instance);
-    EXPECT_EQ(ProcessDataState::kAllFramesHaveDistinctSiteInstances,
-              TestIsolationContextMetrics::GetProcessDataState(data1));
-
-    // Expect metrics to have been reported on the state change.
-    EXPECT_EQ(task_env().NowTicks(), data1->last_reported);
-    histogram_tester_.ExpectUniqueSample(
-        metrics_->kProcessDataByTimeHistogramName,
-        ProcessDataState::kOnlyOneFrameExists,
-        metrics_->kReportingInterval.InSeconds() + 1);
-    histogram_tester_.ExpectTotalCount(
-        metrics_->kProcessDataByProcessHistogramName, 0);
-    histogram_tester_.ExpectBucketCount(
-        metrics_->kFramesPerRendererByTimeHistogram, 1,
-        metrics_->kReportingInterval.InSeconds());
-    histogram_tester_.ExpectBucketCount(
-        metrics_->kFramesPerRendererByTimeHistogram, 2, 1);
-    histogram_tester_.ExpectBucketCount(
-        metrics_->kSiteInstancesPerRendererByTimeHistogram, 1,
-        metrics_->kReportingInterval.InSeconds());
-    histogram_tester_.ExpectBucketCount(
-        metrics_->kSiteInstancesPerRendererByTimeHistogram, 2, 1);
-
-    // Advance time.
-    AdvanceClock(base::Seconds(1));
-  }
-
-  // The second frame will be destroyed as it goes out of scope. Expect another
-  // flush of metrics.
-  EXPECT_EQ(task_env().NowTicks(), data1->last_reported);
-  histogram_tester_.ExpectTotalCount(
-      metrics_->kProcessDataByTimeHistogramName,
-      metrics_->kReportingInterval.InSeconds() + 2);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kProcessDataByTimeHistogramName,
-      ProcessDataState::kAllFramesHaveDistinctSiteInstances, 1);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kProcessDataByTimeHistogramName,
-      ProcessDataState::kOnlyOneFrameExists,
-      metrics_->kReportingInterval.InSeconds() + 1);
-  histogram_tester_.ExpectTotalCount(
-      metrics_->kProcessDataByProcessHistogramName, 0);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kFramesPerRendererByTimeHistogram, 1,
-      metrics_->kReportingInterval.InSeconds() + 1);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kFramesPerRendererByTimeHistogram, 2, 1);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kSiteInstancesPerRendererByTimeHistogram, 1,
-      metrics_->kReportingInterval.InSeconds() + 1);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kSiteInstancesPerRendererByTimeHistogram, 2, 1);
-
-  {
-    // Advance time and add another frame to the same site instance, as a child
-    // of |frame1|.
-    AdvanceClock(base::Seconds(1));
-    auto frame2 =
-        CreateFrameNode(process.get(), page.get(), kBID1, kSID1, frame1.get());
-    EXPECT_EQ(1u, data1->site_instance_frame_count.size());
-    EXPECT_EQ(2, data1->frame_count);
-    EXPECT_EQ(1, data1->multi_frame_site_instance_count);
-    EXPECT_TRUE(data1->has_hosted_multiple_frames);
-    EXPECT_TRUE(data1->has_hosted_multiple_frames_with_same_site_instance);
-    EXPECT_EQ(ProcessDataState::kSomeFramesHaveSameSiteInstance,
-              TestIsolationContextMetrics::GetProcessDataState(data1));
-
-    // Expect metrics to have been reported on the state change.
-    EXPECT_EQ(task_env().NowTicks(), data1->last_reported);
-    histogram_tester_.ExpectTotalCount(
-        metrics_->kProcessDataByTimeHistogramName,
-        metrics_->kReportingInterval.InSeconds() + 3);
-    histogram_tester_.ExpectBucketCount(
-        metrics_->kProcessDataByTimeHistogramName,
-        ProcessDataState::kAllFramesHaveDistinctSiteInstances, 1);
-    histogram_tester_.ExpectBucketCount(
-        metrics_->kProcessDataByTimeHistogramName,
-        ProcessDataState::kOnlyOneFrameExists,
-        metrics_->kReportingInterval.InSeconds() + 2);
-    histogram_tester_.ExpectTotalCount(
-        metrics_->kProcessDataByProcessHistogramName, 0);
-    histogram_tester_.ExpectBucketCount(
-        metrics_->kFramesPerRendererByTimeHistogram, 1,
-        metrics_->kReportingInterval.InSeconds() + 1);
-    histogram_tester_.ExpectBucketCount(
-        metrics_->kFramesPerRendererByTimeHistogram, 2, 2);
-    histogram_tester_.ExpectBucketCount(
-        metrics_->kSiteInstancesPerRendererByTimeHistogram, 1,
-        metrics_->kReportingInterval.InSeconds() + 2);
-    histogram_tester_.ExpectBucketCount(
-        metrics_->kSiteInstancesPerRendererByTimeHistogram, 2, 1);
-
-    // Advance time.
-    AdvanceClock(base::Seconds(1));
-  }
-
-  // The second frame will be destroyed as it goes out of scope. Expect another
-  // flush of metrics.
-  EXPECT_EQ(task_env().NowTicks(), data1->last_reported);
-  histogram_tester_.ExpectTotalCount(
-      metrics_->kProcessDataByTimeHistogramName,
-      metrics_->kReportingInterval.InSeconds() + 4);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kProcessDataByTimeHistogramName,
-      ProcessDataState::kAllFramesHaveDistinctSiteInstances, 1);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kProcessDataByTimeHistogramName,
-      ProcessDataState::kSomeFramesHaveSameSiteInstance, 1);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kProcessDataByTimeHistogramName,
-      ProcessDataState::kOnlyOneFrameExists,
-      metrics_->kReportingInterval.InSeconds() + 2);
-  histogram_tester_.ExpectTotalCount(
-      metrics_->kProcessDataByProcessHistogramName, 0);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kFramesPerRendererByTimeHistogram, 1,
-      metrics_->kReportingInterval.InSeconds() + 2);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kFramesPerRendererByTimeHistogram, 2, 2);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kSiteInstancesPerRendererByTimeHistogram, 1,
-      metrics_->kReportingInterval.InSeconds() + 3);
-  histogram_tester_.ExpectBucketCount(
-      metrics_->kSiteInstancesPerRendererByTimeHistogram, 2, 1);
-
-  // Destroy the other frame and the page. No metrics should be flushed.
-  {
-    base::HistogramTester tester;
-    frame1.reset();
-    page.reset();
-    tester.ExpectTotalCount(metrics_->kProcessDataByTimeHistogramName, 0);
-    tester.ExpectTotalCount(metrics_->kProcessDataByProcessHistogramName, 0);
-  }
-
-  // Finally, destroy the process. This should flush metrics to the
-  // "by process" histogram.
-  {
-    base::HistogramTester tester;
-    process.reset();
-    tester.ExpectTotalCount(metrics_->kProcessDataByTimeHistogramName, 0);
-    tester.ExpectUniqueSample(metrics_->kProcessDataByProcessHistogramName,
-                              ProcessDataState::kSomeFramesHaveSameSiteInstance,
-                              1);
-  }
-
-  // Ensure that the empty process never ended up having ProcessData created
-  // for it.
-  EXPECT_FALSE(ProcessData::Get(empty_process.get()));
-
-  // Destroy the empty process and expect no new metrics.
-  {
-    base::HistogramTester tester;
-    empty_process.reset();
-    tester.ExpectTotalCount(metrics_->kProcessDataByTimeHistogramName, 0);
-    tester.ExpectTotalCount(metrics_->kProcessDataByProcessHistogramName, 0);
-  }
-}
-
-}  // namespace performance_manager
diff --git a/chrome/browser/permissions/chrome_permissions_client.cc b/chrome/browser/permissions/chrome_permissions_client.cc
index 2b754b2..88b4e16 100644
--- a/chrome/browser/permissions/chrome_permissions_client.cc
+++ b/chrome/browser/permissions/chrome_permissions_client.cc
@@ -286,7 +286,7 @@
 
 permissions::IconId ChromePermissionsClient::GetOverrideIconId(
     permissions::RequestType request_type) {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
   // TODO(xhwang): fix this icon, see crbug.com/446263.
   if (request_type == permissions::RequestType::kProtectedMediaIdentifier)
     return kProductIcon;
diff --git a/chrome/browser/policy/android/BUILD.gn b/chrome/browser/policy/android/BUILD.gn
index 6a171104..599c39f 100644
--- a/chrome/browser/policy/android/BUILD.gn
+++ b/chrome/browser/policy/android/BUILD.gn
@@ -24,6 +24,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/profiles/android:java",
     "//components/policy/android:policy_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/chrome/browser/preferences/BUILD.gn b/chrome/browser/preferences/BUILD.gn
index 311ec2f..d9d366e 100644
--- a/chrome/browser/preferences/BUILD.gn
+++ b/chrome/browser/preferences/BUILD.gn
@@ -17,6 +17,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/accessibility/android:constants_java",
     "//components/browser_ui/share/android:constants_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/chrome/browser/prefetch/android/BUILD.gn b/chrome/browser/prefetch/android/BUILD.gn
index d7e98a5a..c09025d5 100644
--- a/chrome/browser/prefetch/android/BUILD.gn
+++ b/chrome/browser/prefetch/android/BUILD.gn
@@ -21,6 +21,7 @@
     ":java_resources",
     ":jni_headers",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/android/lifecycle:java",
     "//chrome/browser/feedback/android:java",
     "//chrome/browser/flags:java",
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
index 0530828a..5482de9e79 100644
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
@@ -229,7 +229,7 @@
   // If there is an error, either cancel the request or fallback depending on
   // whether we still have a parent pointer.
   if (!can_be_served_.value()) {
-    if (SearchPrefetchBlockBeforeHeadersIsEnabled() &&
+    if ((navigation_prefetch_ || SearchPrefetchBlockBeforeHeadersIsEnabled()) &&
         !streaming_prefetch_request_) {
       Fallback();
       return;
@@ -545,7 +545,7 @@
 
 void StreamingSearchPrefetchURLLoader::Fallback() {
   DCHECK(!is_in_fallback_);
-  DCHECK(SearchPrefetchBlockBeforeHeadersIsEnabled());
+  DCHECK(navigation_prefetch_ || SearchPrefetchBlockBeforeHeadersIsEnabled());
 
   network_url_loader_.reset();
   url_loader_receiver_.reset();
diff --git a/chrome/browser/printing/print_backend_service_manager.cc b/chrome/browser/printing/print_backend_service_manager.cc
index 27eb7cf..f86651e 100644
--- a/chrome/browser/printing/print_backend_service_manager.cc
+++ b/chrome/browser/printing/print_backend_service_manager.cc
@@ -25,6 +25,7 @@
 #include "content/public/browser/service_process_host.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "printing/backend/print_backend.h"
+#include "printing/printing_features.h"
 
 #if BUILDFLAG(IS_WIN)
 #include "base/win/win_util.h"
@@ -557,12 +558,13 @@
   // Determine if sandboxing is appropriate.  This might be already known for
   // certain drivers/configurations, or learned during runtime.
   bool should_sandbox =
+      features::kEnableOopPrintDriversSandbox.Get() &&
       !PrinterDriverFoundToRequireElevatedPrivilege(printer_name);
 #if BUILDFLAG(IS_WIN)
-  bool avoid_sandbox =
-      PrinterDriverKnownToRequireElevatedPrivilege(printer_name, client_type);
-  if (avoid_sandbox)
-    should_sandbox = false;
+  if (should_sandbox) {
+    should_sandbox = !PrinterDriverKnownToRequireElevatedPrivilege(printer_name,
+                                                                   client_type);
+  }
 #endif
   *is_sandboxed = should_sandbox;
 
@@ -580,18 +582,17 @@
   // be needed by client callers.
   DCHECK_GT(GetClientsRegisteredCount(), 0u);
 
-  // On the first print make note that so far no drivers have been discovered
-  // to require fallback beyond any predetermined known cases.
-  static bool first_print = true;
-  if (first_print) {
-#if BUILDFLAG(IS_WIN)
-    DCHECK(should_sandbox || avoid_sandbox);
-#else
-    DCHECK(should_sandbox);
-#endif
-    first_print = false;
-    base::UmaHistogramBoolean(
-        kPrintBackendRequiresElevatedPrivilegeHistogramName, /*sample=*/false);
+  if (should_sandbox) {
+    // On the first print that will try to use sandboxed service, make note that
+    // so far no drivers have been discovered to require fallback beyond any
+    // predetermined known cases.
+    static bool first_sandboxed_print = true;
+    if (first_sandboxed_print) {
+      first_sandboxed_print = false;
+      base::UmaHistogramBoolean(
+          kPrintBackendRequiresElevatedPrivilegeHistogramName,
+          /*sample=*/false);
+    }
   }
 
   std::string remote_id = GetRemoteIdForPrinterName(printer_name);
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc
index 4858d16..efa7239 100644
--- a/chrome/browser/printing/print_browsertest.cc
+++ b/chrome/browser/printing/print_browsertest.cc
@@ -2373,12 +2373,17 @@
 
   virtual bool UseService() = 0;
 
+  // Only of interest when `UseService()` returns true.
+  virtual bool SandboxService() = 0;
+
   void SetUp() override {
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
     if (UseService()) {
       feature_list_.InitAndEnableFeatureWithParameters(
           features::kEnableOopPrintDrivers,
-          {{features::kEnableOopPrintDriversJobPrint.name, "true"}});
+          {{features::kEnableOopPrintDriversJobPrint.name, "true"},
+           {features::kEnableOopPrintDriversSandbox.name,
+            SandboxService() ? "true" : "false"}});
 
       // Safe to use `base::Unretained(this)` since this testing class
       // necessarily must outlive all interactions from the tests which will
@@ -2786,25 +2791,62 @@
   bool stop_invoked_ = false;
 };
 
-class PrintBackendPrintBrowserTestService
+class PrintBackendPrintBrowserTestSandboxedService
     : public PrintBackendPrintBrowserTestBase {
  public:
+  PrintBackendPrintBrowserTestSandboxedService() = default;
+  ~PrintBackendPrintBrowserTestSandboxedService() override = default;
+
+  bool UseService() override { return true; }
+  bool SandboxService() override { return true; }
+};
+
+class PrintBackendPrintBrowserTestService
+    : public PrintBackendPrintBrowserTestBase,
+      public testing::WithParamInterface<bool> {
+ public:
   PrintBackendPrintBrowserTestService() = default;
   ~PrintBackendPrintBrowserTestService() override = default;
 
   bool UseService() override { return true; }
+  bool SandboxService() override { return GetParam(); }
 };
 
-class PrintBackendPrintBrowserTest : public PrintBackendPrintBrowserTestBase,
-                                     public testing::WithParamInterface<bool> {
+INSTANTIATE_TEST_SUITE_P(All,
+                         PrintBackendPrintBrowserTestService,
+                         testing::Bool());
+
+enum class PrintBackendFeatureVariation {
+  // `PrintBackend` calls occur from browser process.
+  kInBrowserProcess,
+  // Use OOP `PrintBackend`.  Attempt to have `PrintBackendService` be
+  // sandboxed.
+  kOopSandboxedService,
+  // Use OOP `PrintBackend`.  Always use `PrintBackendService` unsandboxed.
+  kOopUnsandboxedService,
+};
+
+class PrintBackendPrintBrowserTest
+    : public PrintBackendPrintBrowserTestBase,
+      public testing::WithParamInterface<PrintBackendFeatureVariation> {
  public:
   PrintBackendPrintBrowserTest() = default;
   ~PrintBackendPrintBrowserTest() override = default;
 
-  bool UseService() override { return GetParam(); }
+  bool UseService() override {
+    return GetParam() != PrintBackendFeatureVariation::kInBrowserProcess;
+  }
+  bool SandboxService() override {
+    return GetParam() == PrintBackendFeatureVariation::kOopSandboxedService;
+  }
 };
 
-INSTANTIATE_TEST_SUITE_P(All, PrintBackendPrintBrowserTest, testing::Bool());
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    PrintBackendPrintBrowserTest,
+    testing::Values(PrintBackendFeatureVariation::kInBrowserProcess,
+                    PrintBackendFeatureVariation::kOopSandboxedService,
+                    PrintBackendFeatureVariation::kOopUnsandboxedService));
 
 IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTest, UpdatePrintSettings) {
   AddPrinter("printer1");
@@ -2854,7 +2896,7 @@
 
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestService, StartPrinting) {
+IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService, StartPrinting) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
 
@@ -2887,7 +2929,7 @@
   EXPECT_TRUE(stop_invoked());
 }
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService,
                        StartPrintingSpoolingSharedMemoryError) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -2918,7 +2960,7 @@
   EXPECT_TRUE(stop_invoked());
 }
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestSandboxedService,
                        StartPrintingAccessDenied) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -2955,7 +2997,7 @@
   EXPECT_TRUE(stop_invoked());
 }
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestSandboxedService,
                        StartPrintingRepeatedAccessDenied) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -2986,7 +3028,7 @@
 }
 
 #if BUILDFLAG(IS_WIN)
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestSandboxedService,
                        StartPrintingRenderPageAccessDenied) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3021,7 +3063,7 @@
 
 // TODO(crbug.com/1008222)  Include Windows once XPS print pipeline is added.
 #if !BUILDFLAG(IS_WIN)
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestSandboxedService,
                        StartPrintingRenderDocumentAccessDenied) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3053,7 +3095,7 @@
 }
 #endif  // !BUILDFLAG(IS_WIN)
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestSandboxedService,
                        StartPrintingDocumentDoneAccessDenied) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3095,7 +3137,7 @@
 // TODO(crbug.com/809738)  Extend to Linux once Wayland can be made to support
 // a system be modal against an application window in the browser process.
 #if BUILDFLAG(IS_WIN)
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestService, StartBasicPrint) {
+IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService, StartBasicPrint) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
 
@@ -3129,7 +3171,7 @@
   EXPECT_TRUE(stop_invoked());
 }
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService,
                        StartBasicPrintCancel) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3159,7 +3201,7 @@
   EXPECT_TRUE(stop_invoked());
 }
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService,
                        StartBasicPrintConcurrent) {
   ASSERT_TRUE(embedded_test_server()->Started());
   GURL url(embedded_test_server()->GetURL("/printing/test3.html"));
@@ -3191,7 +3233,7 @@
 }
 #endif  // BUILDFLAG(IS_WIN)
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService,
                        StartBasicPrintUseDefaultFails) {
   PrimeForFailInUseDefaultSettings();
 
diff --git a/chrome/browser/privacy/BUILD.gn b/chrome/browser/privacy/BUILD.gn
index 34434baa..27986db5 100644
--- a/chrome/browser/privacy/BUILD.gn
+++ b/chrome/browser/privacy/BUILD.gn
@@ -28,6 +28,7 @@
       ":java_resources",
       ":jni_headers",
       "//base:base_java",
+      "//build/android:build_java",
       "//chrome/browser/android/lifecycle:java",
       "//chrome/browser/flags:java",
       "//chrome/browser/net:secure_dns_management_mode_generated_enum",
diff --git a/chrome/browser/privacy_sandbox/android/BUILD.gn b/chrome/browser/privacy_sandbox/android/BUILD.gn
index 7013737d..f68f765 100644
--- a/chrome/browser/privacy_sandbox/android/BUILD.gn
+++ b/chrome/browser/privacy_sandbox/android/BUILD.gn
@@ -31,6 +31,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/settings:java",
     "//chrome/browser/ui/messages/android:java",
diff --git a/chrome/browser/profiles/android/BUILD.gn b/chrome/browser/profiles/android/BUILD.gn
index d2f4822..547b535f 100644
--- a/chrome/browser/profiles/android/BUILD.gn
+++ b/chrome/browser/profiles/android/BUILD.gn
@@ -9,6 +9,7 @@
 android_library("java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/android/crypto:java",
     "//chrome/browser/preferences:java",
     "//components/embedder_support/android:browser_context_java",
diff --git a/chrome/browser/resources/history/app.ts b/chrome/browser/resources/history/app.ts
index dbe1fa2..b1bce182 100644
--- a/chrome/browser/resources/history/app.ts
+++ b/chrome/browser/resources/history/app.ts
@@ -32,6 +32,7 @@
 import {BrowserService, BrowserServiceImpl} from './browser_service.js';
 import {HistoryPageViewHistogram} from './constants.js';
 import {ForeignSession, QueryResult, QueryState} from './externs.js';
+import {BrowserProxyImpl} from './history_clusters/browser_proxy.js';
 import {HistoryListElement} from './history_list.js';
 import {HistoryToolbarElement} from './history_toolbar.js';
 import {Page, TABBED_PAGES} from './router.js';
@@ -550,6 +551,13 @@
     this.browserService_!.recordHistogram(
         'History.HistoryPageView', histogramValue,
         HistoryPageViewHistogram.END);
+
+    // We don't use `this.browserService_` here, because its chrome.send message
+    // handling is deprecated, and none of the handlers attached to
+    // `this.browserService_` handle History Clusters logic.
+    BrowserProxyImpl.getInstance().handler.notifyHistoryClustersSelected(
+        this.historyClustersSelected_(
+            this.selectedPage_!, this.showHistoryClusters_));
   }
 
   // Override FindShortcutMixin methods.
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html
index 4882d54..401b57c3 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html
@@ -44,7 +44,7 @@
     </div>
     <cr-toggle id="osAppsControl"
         checked="{{osSyncPrefs.osAppsSynced}}"
-        on-change="onAppsSyncedChanged_"
+        on-change="onSingleSyncDataTypeChanged_"
         disabled="[[areDataTypeTogglesDisabled_]]"
         aria-labelledby="osAppsCheckboxLabel">
     </cr-toggle>
@@ -56,7 +56,7 @@
     </div>
     <cr-toggle id="osPreferencesControl"
         checked="{{osSyncPrefs.osPreferencesSynced}}"
-        on-change="onSingleSyncDataTypeChanged_"
+        on-change="onSettingsSyncedChanged_"
         disabled="[[areDataTypeTogglesDisabled_]]"
         aria-labelledby="osSettingsCheckboxLabel">
     </cr-toggle>
@@ -75,10 +75,8 @@
   </div>
   <div class="list-item" hidden="[[!osSyncPrefs.osAppsRegistered]]">
     <!-- Wallpaper sync is a special case; its implementation relies upon
-         the chrome.storage.sync API, which is controlled by the apps
-         toggle. Thus, the wallpaper label and toggle are only shown when
-         apps are registered and are disabled if apps syncing is off.
-         TODO(https://crbug.com/967987): Break this dependency. -->
+         OS Settings to be synced. Thus, the wallpaper label and toggle are
+         only enabled when the Settings sync toggle above is on. -->
     <div id="wallpaperCheckboxLabel"
         label-disabled$="[[shouldWallpaperSyncSectionBeDisabled_(
             areDataTypeTogglesDisabled_, osSyncPrefs.osAppsSynced)]]">
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js
index 01b207f..ae565f4 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js
@@ -141,7 +141,7 @@
     this.osSyncPrefs = osSyncPrefs;
 
     // If apps are not registered or synced, force wallpaper off.
-    if (!this.osSyncPrefs.osAppsRegistered || !this.osSyncPrefs.osAppsSynced) {
+    if (!this.osSyncPrefs.osPreferencesSynced) {
       this.set('osSyncPrefs.wallpaperEnabled', false);
     }
   },
@@ -191,13 +191,14 @@
   },
 
   /**
-   * Handler for changes to the apps sync state; apps have a special handler
-   * instead of relying on onSingleSyncDataTypeChanged_() because wallpaper has
-   * a dependency on apps.
+   * Handler for changes to the settings sync state; settings have a special
+   * handler instead of relying on onSingleSyncDataTypeChanged_() because
+   * wallpaper has a dependency on it.
    * @private
    */
-  onAppsSyncedChanged_() {
-    this.set('osSyncPrefs.wallpaperEnabled', this.osSyncPrefs.osAppsSynced);
+  onSettingsSyncedChanged_() {
+    this.set(
+        'osSyncPrefs.wallpaperEnabled', this.osSyncPrefs.osPreferencesSynced);
 
     this.onSingleSyncDataTypeChanged_();
   },
@@ -236,6 +237,6 @@
    */
   shouldWallpaperSyncSectionBeDisabled_() {
     return this.areDataTypeTogglesDisabled_ || !this.osSyncPrefs ||
-        !this.osSyncPrefs.osAppsSynced;
+        !this.osSyncPrefs.osPreferencesSynced;
   },
 });
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_dialog.html b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_dialog.html
index 71d21cf..48606c1 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_dialog.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_dialog.html
@@ -12,9 +12,16 @@
   cr-dialog::part(dialog) {
     border-radius: 0;
     height: 100vh;
+    overflow: auto;
     width: 100vw;
   }
 
+  cr-dialog::part(wrapper),
+  cr-dialog::part(body-container) {
+    max-height: none;
+    overflow: visible;
+  }
+
   settings-privacy-guide-page {
     margin: auto;
   }
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts
index 3fb44dfea..83574c2 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts
+++ b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts
@@ -428,6 +428,9 @@
             animateFromLeftToRight ? 'slide-in-fade-in-ltr' :
                                      'slide-in-fade-in-rtl',
             'no-animation');
+      } else if (this.animationsEnabled_ && this.isPrivacyGuideV2) {
+        this.$.viewManager.switchView(
+            this.privacyGuideStep_, 'no-animation', 'fade-out');
       } else {
         this.$.viewManager.switchView(
             this.privacyGuideStep_, 'no-animation', 'no-animation');
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index 05d8339..3c88396 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -737,10 +737,10 @@
         </settings-subpage>
       </template>
       <template is="dom-if" route-path="/content/protectedContent" no-search>
-<if expr="not chromeos_ash and not is_win">
+<if expr="not chromeos_ash and not chromeos_lacros and not is_win">
         <settings-subpage page-title="$i18n{siteSettingsProtectedContent}">
 </if>
-<if expr="chromeos_ash or is_win">
+<if expr="chromeos_ash or chromeos_lacros or is_win">
         <settings-subpage page-title="$i18n{siteSettingsProtectedContent}"
             search-label="$i18n{siteSettingsAllSitesSearch}"
             search-term="{{searchFilter_}}">
@@ -774,7 +774,7 @@
               </settings-collapse-radio-button>
             </settings-radio-group>
           </div>
-<if expr="chromeos_ash or is_win">
+<if expr="chromeos_ash or chromeos_lacros or is_win">
           <settings-category-default-radio-group
             header="$i18n{siteSettingsProtectedContentIdentifiers}"
             description=
diff --git a/chrome/browser/resources/settings/site_settings/site_details.html b/chrome/browser/resources/settings/site_settings/site_details.html
index 39e64370..bb2a12d 100644
--- a/chrome/browser/resources/settings/site_settings/site_details.html
+++ b/chrome/browser/resources/settings/site_settings/site_details.html
@@ -171,7 +171,7 @@
       <site-details-permission category="[[contentSettingsTypesEnum_.HID_DEVICES]]"
           icon="settings:hid-device" label="$i18n{siteSettingsHidDevices}">
       </site-details-permission>
-<if expr="chromeos_ash or is_win">
+<if expr="chromeos_ash or chromeos_lacros or is_win">
       <site-details-permission
           category="[[contentSettingsTypesEnum_.PROTECTED_CONTENT]]"
           icon="settings:protected-content"
diff --git a/chrome/browser/safe_browsing/android/BUILD.gn b/chrome/browser/safe_browsing/android/BUILD.gn
index 1d44800..86f6a37e 100644
--- a/chrome/browser/safe_browsing/android/BUILD.gn
+++ b/chrome/browser/safe_browsing/android/BUILD.gn
@@ -46,6 +46,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/feedback/android:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_persister_unittest.cc b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_persister_unittest.cc
index 3d28212..39adc85 100644
--- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_persister_unittest.cc
+++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_persister_unittest.cc
@@ -30,7 +30,7 @@
     success_ = success;
   }
 
-  content::BrowserTaskEnvironment task_environment_;
+  base::test::TaskEnvironment task_environment_;
   bool success_;
   std::string read_string_;
   base::WeakPtrFactory<ExtensionTelemetryPersisterTest> weak_factory_{this};
@@ -44,8 +44,6 @@
 }
 
 TEST_F(ExtensionTelemetryPersisterTest, WriteReadCheck) {
-  // Ensure all files are clear then write one file.
-  persister_->ClearPersistedFiles();
   std::string written_string = "Test String 1";
   persister_->WriteReport(written_string);
   task_environment_.RunUntilIdle();
@@ -59,46 +57,43 @@
   EXPECT_EQ(success_, true);
   EXPECT_EQ(written_string, read_string_);
   persister_->ClearPersistedFiles();
+  task_environment_.RunUntilIdle();
 }
 
-// TODO(crbug.com/1312282): Flaky on Linux TSAN builder.
-#if BUILDFLAG(IS_LINUX) && defined(THREAD_SANITIZER)
-#define MAYBE_WritePastFullCacheCheck DISABLED_WritePastFullCacheCheck
-#else
-#define MAYBE_WritePastFullCacheCheck WritePastFullCacheCheck
-#endif
-TEST_F(ExtensionTelemetryPersisterTest, MAYBE_WritePastFullCacheCheck) {
-  persister_->ClearPersistedFiles();
+TEST_F(ExtensionTelemetryPersisterTest, WritePastFullCacheCheck) {
   read_string_ = "No File was read";
   std::string written_string = "Test String 1";
   for (int i = 0; i < 12; i++) {
     persister_->WriteReport(written_string);
+    task_environment_.RunUntilIdle();
   }
-  task_environment_.RunUntilIdle();
   persister_->ClearPersistedFiles();
+  task_environment_.RunUntilIdle();
   // After a clear no file should be there to read from.
   auto callback = base::BindPostTask(
       base::SequencedTaskRunnerHandle::Get(),
       base::BindOnce(&ExtensionTelemetryPersisterTest::CallbackHelper,
                      weak_factory_.GetWeakPtr()));
   persister_->ReadReport(std::move(callback));
+  task_environment_.RunUntilIdle();
   EXPECT_NE(written_string, read_string_);
   persister_->ClearPersistedFiles();
+  task_environment_.RunUntilIdle();
 }
 
 TEST_F(ExtensionTelemetryPersisterTest, ReadFullCache) {
-  persister_->ClearPersistedFiles();
   // Fully load persisted cache.
   std::string written_string = "Test String 1";
   for (int i = 0; i < 10; i++) {
     persister_->WriteReport(written_string);
+    task_environment_.RunUntilIdle();
   }
   written_string = "Test String 2";
   // Overwrite first 5 files.
   for (int i = 0; i < 5; i++) {
     persister_->WriteReport(written_string);
+    task_environment_.RunUntilIdle();
   }
-  task_environment_.RunUntilIdle();
   //  Read should start at highest numbered file.
   for (int i = 0; i < 5; i++) {
     auto callback = base::BindPostTask(
@@ -109,7 +104,6 @@
     task_environment_.RunUntilIdle();
     EXPECT_EQ(success_, true);
     EXPECT_EQ("Test String 1", read_string_);
-    task_environment_.RunUntilIdle();
   }
   // Files 0-4 should be different.
   for (int i = 0; i < 5; i++) {
@@ -121,7 +115,6 @@
     task_environment_.RunUntilIdle();
     EXPECT_EQ(success_, true);
     EXPECT_EQ("Test String 2", read_string_);
-    task_environment_.RunUntilIdle();
   }
   auto callback = base::BindPostTask(
       base::SequencedTaskRunnerHandle::Get(),
@@ -132,5 +125,6 @@
   // Last read should not happen as all files have been read.
   EXPECT_EQ(success_, false);
   persister_->ClearPersistedFiles();
+  task_environment_.RunUntilIdle();
 }
 }  // namespace safe_browsing
diff --git a/chrome/browser/safety_check/android/BUILD.gn b/chrome/browser/safety_check/android/BUILD.gn
index 68a227b..8fb2c68c 100644
--- a/chrome/browser/safety_check/android/BUILD.gn
+++ b/chrome/browser/safety_check/android/BUILD.gn
@@ -37,6 +37,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/password_check:public_java",
     "//chrome/browser/password_check/android:password_check_java_enums",
@@ -103,6 +104,7 @@
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/password_check:public_java",
     "//chrome/browser/password_check/android:password_check_java_enums",
diff --git a/chrome/browser/search_engines/android/BUILD.gn b/chrome/browser/search_engines/android/BUILD.gn
index 9f2e3b1..28c236fd 100644
--- a/chrome/browser/search_engines/android/BUILD.gn
+++ b/chrome/browser/search_engines/android/BUILD.gn
@@ -25,6 +25,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/omaha/android:java",
     "//chrome/browser/preferences:java",
diff --git a/chrome/browser/segmentation_platform/BUILD.gn b/chrome/browser/segmentation_platform/BUILD.gn
index 562d749..ddd7675 100644
--- a/chrome/browser/segmentation_platform/BUILD.gn
+++ b/chrome/browser/segmentation_platform/BUILD.gn
@@ -13,6 +13,7 @@
 
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//chrome/browser/profiles/android:java",
       "//components/segmentation_platform/public:public_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/chrome/browser/share/BUILD.gn b/chrome/browser/share/BUILD.gn
index 7dd8e30..a9201551 100644
--- a/chrome/browser/share/BUILD.gn
+++ b/chrome/browser/share/BUILD.gn
@@ -69,6 +69,7 @@
     deps = [
       ":jni_headers",
       "//base:base_java",
+      "//build/android:build_java",
       "//chrome/browser/preferences:java",
       "//chrome/browser/profiles/android:java",
       "//chrome/browser/tab:java",
diff --git a/chrome/browser/signin/services/android/BUILD.gn b/chrome/browser/signin/services/android/BUILD.gn
index 1ecf35d..b91b512a 100644
--- a/chrome/browser/signin/services/android/BUILD.gn
+++ b/chrome/browser/signin/services/android/BUILD.gn
@@ -30,6 +30,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
diff --git a/chrome/browser/subresource_filter/BUILD.gn b/chrome/browser/subresource_filter/BUILD.gn
index 77f802c2..47f14e7 100644
--- a/chrome/browser/subresource_filter/BUILD.gn
+++ b/chrome/browser/subresource_filter/BUILD.gn
@@ -14,7 +14,10 @@
   android_library("subresource_filter_java_test_support") {
     testonly = true
     sources = [ "../../android/javatests/src/org/chromium/chrome/browser/subresource_filter/TestRulesetPublisher.java" ]
-    deps = [ "//base:base_java" ]
+    deps = [
+      "//base:base_java",
+      "//build/android:build_java",
+    ]
   }
 
   android_library("subresource_filter_javatests") {
diff --git a/chrome/browser/supervised_user/OWNERS b/chrome/browser/supervised_user/OWNERS
index 629596a..37a5d265 100644
--- a/chrome/browser/supervised_user/OWNERS
+++ b/chrome/browser/supervised_user/OWNERS
@@ -1,7 +1,12 @@
+#ChromeOS
 agawronska@chromium.org
 danan@chromium.org
 llin@chromium.org
 michaelpg@chromium.org
 
+#Chrome Browser
+fernandex@chromium.org
+ljjlee@google.com
+
 # Previous owner, feel free to add for any questions or historical context:
 # treib@chromium.org
diff --git a/chrome/browser/sync/android/BUILD.gn b/chrome/browser/sync/android/BUILD.gn
index 7b8309e..3bf17ea4 100644
--- a/chrome/browser/sync/android/BUILD.gn
+++ b/chrome/browser/sync/android/BUILD.gn
@@ -8,6 +8,7 @@
 android_library("java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/signin/public/android:java",
     "//components/sync/android:sync_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/chrome/browser/tab/BUILD.gn b/chrome/browser/tab/BUILD.gn
index f41f849..9fdf17aa 100644
--- a/chrome/browser/tab/BUILD.gn
+++ b/chrome/browser/tab/BUILD.gn
@@ -69,6 +69,7 @@
     ":critical_persisted_tab_data_proto_java",
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/android/crypto:java",
     "//chrome/browser/commerce/android:java",
     "//chrome/browser/contextmenu:java",
diff --git a/chrome/browser/tab_group/BUILD.gn b/chrome/browser/tab_group/BUILD.gn
index 53cc4bf..32b85fd8 100644
--- a/chrome/browser/tab_group/BUILD.gn
+++ b/chrome/browser/tab_group/BUILD.gn
@@ -35,6 +35,7 @@
     ":java",
     "//base:base_java",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/browser/tab:java",
     "//chrome/browser/tabmodel:java",
     "//chrome/test/android:chrome_java_test_support",
diff --git a/chrome/browser/tabmodel/BUILD.gn b/chrome/browser/tabmodel/BUILD.gn
index e95cace2..3bfced4e 100644
--- a/chrome/browser/tabmodel/BUILD.gn
+++ b/chrome/browser/tabmodel/BUILD.gn
@@ -46,6 +46,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/tab:java",
     "//components/embedder_support/android:util_java",
diff --git a/chrome/browser/tabpersistence/BUILD.gn b/chrome/browser/tabpersistence/BUILD.gn
index 91a667d6..0f8cdd86 100644
--- a/chrome/browser/tabpersistence/BUILD.gn
+++ b/chrome/browser/tabpersistence/BUILD.gn
@@ -30,6 +30,7 @@
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//chrome/browser/tab:java",
     "//chrome/test/android:chrome_java_test_support",
     "//third_party/android_deps:robolectric_all_java",
diff --git a/chrome/browser/test_dummy/internal/BUILD.gn b/chrome/browser/test_dummy/internal/BUILD.gn
index a4d5bb2..f70aebf 100644
--- a/chrome/browser/test_dummy/internal/BUILD.gn
+++ b/chrome/browser/test_dummy/internal/BUILD.gn
@@ -16,6 +16,7 @@
     ":base_module_java",
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/test_dummy:java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
diff --git a/chrome/browser/thumbnail/generator/BUILD.gn b/chrome/browser/thumbnail/generator/BUILD.gn
index ee2c5e3..0129f3c 100644
--- a/chrome/browser/thumbnail/generator/BUILD.gn
+++ b/chrome/browser/thumbnail/generator/BUILD.gn
@@ -72,6 +72,7 @@
       ":jni_headers",
       ":proto_java",
       "//base:base_java",
+      "//build/android:build_java",
       "//chrome/browser/util:java",
       "//components/browser_ui/util/android:java",
       "//content/public/android:content_java",
@@ -159,6 +160,7 @@
     deps = [
       ":test_support_jni_headers",
       "//base:base_java",
+      "//build/android:build_java",
     ]
 
     annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/chrome/browser/touch_to_fill/android/BUILD.gn b/chrome/browser/touch_to_fill/android/BUILD.gn
index 079a203..64d60a2 100644
--- a/chrome/browser/touch_to_fill/android/BUILD.gn
+++ b/chrome/browser/touch_to_fill/android/BUILD.gn
@@ -57,6 +57,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_test_util_java",
     "//chrome/browser/flags:java",
@@ -91,6 +92,7 @@
     ":public_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_test_java",
     "//chrome/android:chrome_test_util_java",
diff --git a/chrome/browser/touch_to_fill/android/internal/BUILD.gn b/chrome/browser/touch_to_fill/android/internal/BUILD.gn
index 05e0cd0a..d49c1ea6 100644
--- a/chrome/browser/touch_to_fill/android/internal/BUILD.gn
+++ b/chrome/browser/touch_to_fill/android/internal/BUILD.gn
@@ -11,6 +11,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/profiles/android:java",
diff --git a/chrome/browser/ui/android/appmenu/internal/BUILD.gn b/chrome/browser/ui/android/appmenu/internal/BUILD.gn
index 7a8f3bef..0eb54cd 100644
--- a/chrome/browser/ui/android/appmenu/internal/BUILD.gn
+++ b/chrome/browser/ui/android/appmenu/internal/BUILD.gn
@@ -74,6 +74,7 @@
     ":test_java_resources",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/browser/android/lifecycle:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/ui/android/appmenu:java",
diff --git a/chrome/browser/ui/android/appmenu/test/BUILD.gn b/chrome/browser/ui/android/appmenu/test/BUILD.gn
index 33992e3..f99eeb8 100644
--- a/chrome/browser/ui/android/appmenu/test/BUILD.gn
+++ b/chrome/browser/ui/android/appmenu/test/BUILD.gn
@@ -14,6 +14,7 @@
   deps = [
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/browser/ui/android/appmenu:java",
     "//chrome/browser/ui/android/appmenu/internal:java",
     "//ui/android:ui_no_recycler_view_java",
diff --git a/chrome/browser/ui/android/autofill/internal/BUILD.gn b/chrome/browser/ui/android/autofill/internal/BUILD.gn
index 6a40742..5dae98e 100644
--- a/chrome/browser/ui/android/autofill/internal/BUILD.gn
+++ b/chrome/browser/ui/android/autofill/internal/BUILD.gn
@@ -30,6 +30,7 @@
     ":jni_headers",
     "//base:base_java",
     "//base:jni_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_core_core_java",
     "//third_party/androidx:androidx_recyclerview_recyclerview_java",
diff --git a/chrome/browser/ui/android/default_browser_promo/BUILD.gn b/chrome/browser/ui/android/default_browser_promo/BUILD.gn
index 6f28d07..ce8f605a 100644
--- a/chrome/browser/ui/android/default_browser_promo/BUILD.gn
+++ b/chrome/browser/ui/android/default_browser_promo/BUILD.gn
@@ -31,6 +31,7 @@
     ":java",
     "//base:base_java",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//third_party/android_deps:robolectric_all_java",
     "//third_party/junit",
     "//third_party/mockito:mockito_java",
diff --git a/chrome/browser/ui/android/favicon/BUILD.gn b/chrome/browser/ui/android/favicon/BUILD.gn
index 00642d6..dc84d57 100644
--- a/chrome/browser/ui/android/favicon/BUILD.gn
+++ b/chrome/browser/ui/android/favicon/BUILD.gn
@@ -13,6 +13,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/util:java",
     "//components/browser_ui/util/android:java",
diff --git a/chrome/browser/ui/android/layouts/BUILD.gn b/chrome/browser/ui/android/layouts/BUILD.gn
index e40bec0b..ae027493 100644
--- a/chrome/browser/ui/android/layouts/BUILD.gn
+++ b/chrome/browser/ui/android/layouts/BUILD.gn
@@ -26,6 +26,7 @@
   deps = [
     "third_party/float_property:java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/widget/android:java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//ui/android:ui_java",
diff --git a/chrome/browser/ui/android/layouts/test/BUILD.gn b/chrome/browser/ui/android/layouts/test/BUILD.gn
index a9dd4ac..a4bd524 100644
--- a/chrome/browser/ui/android/layouts/test/BUILD.gn
+++ b/chrome/browser/ui/android/layouts/test/BUILD.gn
@@ -14,6 +14,7 @@
     "..:java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/test/android:content_java_test_support",
   ]
 }
diff --git a/chrome/browser/ui/android/logo/BUILD.gn b/chrome/browser/ui/android/logo/BUILD.gn
index c7716dd..d7183ff 100644
--- a/chrome/browser/ui/android/logo/BUILD.gn
+++ b/chrome/browser/ui/android/logo/BUILD.gn
@@ -16,6 +16,7 @@
     ":java_resources",
     "//base:base_java",
     "//base:jni_java",
+    "//build/android:build_java",
     "//chrome/android/features/start_surface:public_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/profiles/android:java",
@@ -88,6 +89,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/android/features/start_surface:public_java",
     "//chrome/browser/flags:java",
diff --git a/chrome/browser/ui/android/multiwindow/BUILD.gn b/chrome/browser/ui/android/multiwindow/BUILD.gn
index 7d6eab7f..e543cb4 100644
--- a/chrome/browser/ui/android/multiwindow/BUILD.gn
+++ b/chrome/browser/ui/android/multiwindow/BUILD.gn
@@ -82,6 +82,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/util:java",
     "//components/favicon/android:java",
@@ -107,6 +108,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
     "//chrome/test/android:chrome_java_test_support",
diff --git a/chrome/browser/ui/android/night_mode/BUILD.gn b/chrome/browser/ui/android/night_mode/BUILD.gn
index a03083f..69ba7ed 100644
--- a/chrome/browser/ui/android/night_mode/BUILD.gn
+++ b/chrome/browser/ui/android/night_mode/BUILD.gn
@@ -85,6 +85,7 @@
     ":night_mode_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/settings:java",
@@ -120,6 +121,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/browser/feature_engagement:java",
     "//chrome/browser/feedback/android:java",
     "//chrome/browser/flags:java",
diff --git a/chrome/browser/ui/android/omnibox/BUILD.gn b/chrome/browser/ui/android/omnibox/BUILD.gn
index d3cceb7a..d89a87d5 100644
--- a/chrome/browser/ui/android/omnibox/BUILD.gn
+++ b/chrome/browser/ui/android/omnibox/BUILD.gn
@@ -137,6 +137,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/android/lifecycle:java",
     "//chrome/browser/browser_controls/android:java",
     "//chrome/browser/commerce/merchant_viewer/android:java",
@@ -233,6 +234,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//chrome/test/android:chrome_java_test_support",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_sdk:android_test_mock_java",
@@ -382,6 +384,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/android:base_module_java",
     "//chrome/browser/device:java",
     "//chrome/browser/flags:java",
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/BUILD.gn b/chrome/browser/ui/android/quickactionsearchwidget/BUILD.gn
index 0f24e9e2a..378b9345 100644
--- a/chrome/browser/ui/android/quickactionsearchwidget/BUILD.gn
+++ b/chrome/browser/ui/android/quickactionsearchwidget/BUILD.gn
@@ -33,6 +33,7 @@
     ":java_resources",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_app_java_resources",
     "//chrome/android:chrome_java",
     "//chrome/browser/android/browserservices/intents:java",
diff --git a/chrome/browser/ui/android/searchactivityutils/BUILD.gn b/chrome/browser/ui/android/searchactivityutils/BUILD.gn
index b4ac2dc..a09c1c6 100644
--- a/chrome/browser/ui/android/searchactivityutils/BUILD.gn
+++ b/chrome/browser/ui/android/searchactivityutils/BUILD.gn
@@ -36,6 +36,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/search_engines/android:java",
     "//components/search_engines/android:java",
diff --git a/chrome/browser/ui/android/signin/BUILD.gn b/chrome/browser/ui/android/signin/BUILD.gn
index e98c4f4..3918471 100644
--- a/chrome/browser/ui/android/signin/BUILD.gn
+++ b/chrome/browser/ui/android/signin/BUILD.gn
@@ -149,6 +149,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chrome/android/features/start_surface:public_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
@@ -192,6 +193,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index cb05d3a730..b55165d 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -555,6 +555,12 @@
       <message name="IDS_AUTOFILL_VIRTUAL_CARD_ENROLLMENT_INFOBAR_CARD_PREFIX" desc="Notifies the user that their virtual card card is linked with a card on their account.">
         linked with
       </message>
+      <message name="IDS_AUTOFILL_CARD_EDITOR_VIRTUAL_CARD_TURN_ON_BUTTON_LABEL" desc="Label shown on the button that the user clicks on to enroll into virtual cards.">
+        Turn on
+      </message>
+      <message name="IDS_AUTOFILL_CARD_EDITOR_VIRTUAL_CARD_TURN_OFF_BUTTON_LABEL" desc="Label shown on the button that the user clicks on to unenroll from virtual cards.">
+        Turn off
+      </message>
 
        <!-- Payment Request section preview strings -->
        <message name="IDS_PAYMENT_REQUEST_PAYMENT_METHODS_PREVIEW" desc="This is a snippet of a payment method a user has saved to Chrome, plus an indication of the number of additional payment methods the user has saved.
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_AUTOFILL_CARD_EDITOR_VIRTUAL_CARD_TURN_OFF_BUTTON_LABEL.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_AUTOFILL_CARD_EDITOR_VIRTUAL_CARD_TURN_OFF_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..66d30d9
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_AUTOFILL_CARD_EDITOR_VIRTUAL_CARD_TURN_OFF_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+899d82f31adba5ec116cd46438e61f5dd5b3ec39
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_AUTOFILL_CARD_EDITOR_VIRTUAL_CARD_TURN_ON_BUTTON_LABEL.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_AUTOFILL_CARD_EDITOR_VIRTUAL_CARD_TURN_ON_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..4659587
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_AUTOFILL_CARD_EDITOR_VIRTUAL_CARD_TURN_ON_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+9143ff7ee7e768bd540aad4fbaab791395f9c962
\ No newline at end of file
diff --git a/chrome/browser/ui/android/toolbar/BUILD.gn b/chrome/browser/ui/android/toolbar/BUILD.gn
index 05a505b..4386000 100644
--- a/chrome/browser/ui/android/toolbar/BUILD.gn
+++ b/chrome/browser/ui/android/toolbar/BUILD.gn
@@ -102,6 +102,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android/features/start_surface:public_java",
     "//chrome/browser/android/lifecycle:java",
     "//chrome/browser/browser_controls/android:java",
@@ -339,6 +340,7 @@
     ":java_resources",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/settings:test_support_java",
diff --git a/chrome/browser/ui/android/webid/internal/BUILD.gn b/chrome/browser/ui/android/webid/internal/BUILD.gn
index bffc42d..81fb11de 100644
--- a/chrome/browser/ui/android/webid/internal/BUILD.gn
+++ b/chrome/browser/ui/android/webid/internal/BUILD.gn
@@ -12,6 +12,7 @@
     ":java_resources",
     "//base:base_java",
     "//base:jni_java",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/profiles/android:java",
@@ -107,6 +108,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
 
     # TODO(majidvp): Remove this dependency after test clean up. https://crbug.com/1214820
     "//chrome/android:chrome_java",
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc b/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc
index 7c8fd26..2f49102 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc
+++ b/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc
@@ -33,6 +33,9 @@
 #include "chrome/browser/ash/crosapi/crosapi_ash.h"
 #include "chrome/browser/ash/crosapi/crosapi_manager.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
+#include "chrome/browser/download/chrome_download_manager_delegate.h"
+#include "chrome/browser/download/download_core_service.h"
+#include "chrome/browser/download/download_core_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_browsertest_base.h"
@@ -41,6 +44,8 @@
 #include "chrome/browser/ui/ash/holding_space/holding_space_util.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "components/download/public/common/mock_download_item.h"
+#include "content/public/browser/download_item_utils.h"
+#include "content/public/browser/download_manager_delegate.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/mock_download_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -1339,11 +1344,18 @@
         base::BindLambdaForTesting([&](content::BrowserContext* context) {
           DCHECK(!download_manager_);
 
-          // Swap out production download manager for a mock.
+          // Create a mock download manager.
           download_manager_ =
               new testing::NiceMock<content::MockDownloadManager>();
-          context->SetDownloadManagerForTesting(
-              base::WrapUnique(download_manager_));
+
+          // Mock `content::DownloadManager::Shutdown()`.
+          ON_CALL(*download_manager_, Shutdown)
+              .WillByDefault(testing::Invoke([&]() {
+                if (download_manager_->GetDelegate()) {
+                  download_manager_->GetDelegate()->Shutdown();
+                  download_manager_->SetDelegate(nullptr);
+                }
+              }));
 
           // Mock `content::DownloadManager::IsManagerInitialized()`.
           ON_CALL(*download_manager_, IsManagerInitialized())
@@ -1363,6 +1375,34 @@
                   &base::ObserverList<content::DownloadManager::Observer>::
                       Unchecked::RemoveObserver));
 
+          // Mock `content::DownloadManager::GetBrowserContext()`.
+          ON_CALL(*download_manager_, GetBrowserContext)
+              .WillByDefault(testing::Return(context));
+
+          // Mock `content::DownloadManager::SetDelegate()`.
+          ON_CALL(*download_manager_, SetDelegate)
+              .WillByDefault(testing::Invoke(
+                  [&](content::DownloadManagerDelegate* delegate) {
+                    download_manager_delegate_ = delegate;
+                  }));
+
+          // Mock `content::DownloadManager::GetDelegate()`.
+          ON_CALL(*download_manager_, GetDelegate)
+              .WillByDefault(testing::Invoke(
+                  [&]() { return download_manager_delegate_; }));
+
+          // Swap out the production download manager for the mock.
+          context->SetDownloadManagerForTesting(
+              base::WrapUnique(download_manager_));
+
+          // Install a new download manager delegate after swapping out the
+          // production download manager so it will properly register itself
+          // with the mock.
+          DownloadCoreServiceFactory::GetForBrowserContext(context)
+              ->SetDownloadManagerDelegateForTesting(
+                  std::make_unique<ChromeDownloadManagerDelegate>(
+                      Profile::FromBrowserContext(context)));
+
           // Resume default construction sequence.
           return HoldingSpaceKeyedServiceFactory::GetDefaultTestingFactory()
               .Run(context);
@@ -1667,6 +1707,10 @@
     auto ash_download_item =
         std::make_unique<testing::NiceMock<download::MockDownloadItem>>();
 
+    content::DownloadItemUtils::AttachInfo(
+        ash_download_item.get(), GetProfile(),
+        /*web_contents=*/nullptr, content::GlobalRenderFrameHostId());
+
     // Mock `download::DownloadItem::Cancel()`.
     ON_CALL(*ash_download_item, Cancel(/*from_user=*/testing::Eq(true)))
         .WillByDefault(testing::InvokeWithoutArgs(
@@ -1686,10 +1730,9 @@
               ash_download_item->NotifyObserversDownloadUpdated();
             }));
 
-    // Mock `download::DownloadItem::GetGuid()`.
-    ON_CALL(*ash_download_item, GetGuid)
-        .WillByDefault(testing::ReturnRefOfCopy(
-            base::GUID::GenerateRandomV4().AsLowercaseString()));
+    // Mock `download::DownloadItem::GetETag()`.
+    ON_CALL(*ash_download_item, GetETag)
+        .WillByDefault(testing::ReturnRefOfCopy(std::string()));
 
     // Mock `download::DownloadItem::GetFullPath()`.
     ON_CALL(*ash_download_item, GetFullPath)
@@ -1702,15 +1745,68 @@
                          : file_path;
             }));
 
+    // Mock `download::DownloadItem::GetGuid()`.
+    ON_CALL(*ash_download_item, GetGuid)
+        .WillByDefault(testing::ReturnRefOfCopy(
+            base::GUID::GenerateRandomV4().AsLowercaseString()));
+
+    // Mock `download::DownloadItem::GetId()`.
+    ON_CALL(*ash_download_item, GetId).WillByDefault(testing::Invoke([]() {
+      static uint32_t kNextId = 1u;
+      return kNextId++;
+    }));
+
+    // Mock `download::DownloadItem::GetLastModifiedTime()`.
+    ON_CALL(*ash_download_item, GetLastModifiedTime)
+        .WillByDefault(testing::ReturnRefOfCopy(std::string()));
+
+    // Mock `download::DownloadItem::GetLastReason()`.
+    ON_CALL(*ash_download_item, GetLastReason)
+        .WillByDefault(
+            testing::Invoke([ash_download_item = ash_download_item.get()]() {
+              return ash_download_item->GetState() ==
+                             download::DownloadItem::CANCELLED
+                         ? download::DownloadInterruptReason::
+                               DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
+                         : download::DownloadInterruptReason::
+                               DOWNLOAD_INTERRUPT_REASON_NONE;
+            }));
+
     // Mock `download::DownloadItem::GetOpenWhenComplete()`.
     auto open_when_complete = std::make_unique<bool>(false);
     ON_CALL(*ash_download_item, GetOpenWhenComplete)
         .WillByDefault(testing::ReturnPointee(open_when_complete.get()));
 
+    // Mock `download::DownloadItem::GetRerouteInfo()`.
+    ON_CALL(*ash_download_item, GetRerouteInfo)
+        .WillByDefault(
+            testing::ReturnRefOfCopy(download::DownloadItemRerouteInfo()));
+
     // Mock `download::DownloadItem::GetReceivedBytes()`.
     ON_CALL(*ash_download_item, GetReceivedBytes)
         .WillByDefault(testing::Return(received_bytes));
 
+    // Mock `download::DownloadItem::GetReceivedSlices()`.
+    ON_CALL(*ash_download_item, GetReceivedSlices)
+        .WillByDefault(testing::ReturnRefOfCopy(
+            std::vector<download::DownloadItem::ReceivedSlice>()));
+
+    // Mock `download::DownloadItem::GetSerializedEmbedderDownloadData()`.
+    ON_CALL(*ash_download_item, GetSerializedEmbedderDownloadData)
+        .WillByDefault(testing::ReturnRefOfCopy(std::string()));
+
+    // Mock `download::DownloadItem::GetReferrerUrl()`.
+    ON_CALL(*ash_download_item, GetReferrerUrl)
+        .WillByDefault(testing::ReturnRefOfCopy(GURL()));
+
+    // Mock `download::DownloadItem::GetTabUrl()`.
+    ON_CALL(*ash_download_item, GetTabUrl)
+        .WillByDefault(testing::ReturnRefOfCopy(GURL()));
+
+    // Mock `download::DownloadItem::GetTabReferrerUrl()`.
+    ON_CALL(*ash_download_item, GetTabReferrerUrl)
+        .WillByDefault(testing::ReturnRefOfCopy(GURL()));
+
     // Mock `download::DownloadItem::GetState()`.
     ON_CALL(*ash_download_item, GetState).WillByDefault(testing::Return(state));
 
@@ -1722,6 +1818,22 @@
     ON_CALL(*ash_download_item, GetTotalBytes)
         .WillByDefault(testing::Return(total_bytes));
 
+    // Mock `download::DownloadItem::GetURL()`.
+    ON_CALL(*ash_download_item, GetURL)
+        .WillByDefault(testing::ReturnRefOfCopy(GURL()));
+
+    // Mock `download::DownloadItem::GetUrlChain()`.
+    ON_CALL(*ash_download_item, GetUrlChain)
+        .WillByDefault(testing::ReturnRefOfCopy(std::vector<GURL>()));
+
+    // Mock `download::DownloadItem::IsDone()`.
+    ON_CALL(*ash_download_item, IsDone)
+        .WillByDefault(
+            testing::Invoke([ash_download_item = ash_download_item.get()]() {
+              return ash_download_item->GetState() ==
+                     download::DownloadItem::COMPLETE;
+            }));
+
     // Mock `download::DownloadItem::IsPaused()`.
     auto paused = std::make_unique<bool>(false);
     ON_CALL(*ash_download_item, IsPaused)
@@ -1884,6 +1996,7 @@
   const DownloadTypeToUse download_type_to_use_;
   base::test::ScopedFeatureList scoped_feature_list_;
   testing::NiceMock<content::MockDownloadManager>* download_manager_ = nullptr;
+  content::DownloadManagerDelegate* download_manager_delegate_ = nullptr;
   base::ObserverList<content::DownloadManager::Observer>::Unchecked
       download_manager_observers_;
   testing::NiceMock<MockDownloadControllerClient> download_controller_client_;
diff --git a/chrome/browser/ui/messages/android/BUILD.gn b/chrome/browser/ui/messages/android/BUILD.gn
index 10cbd69..6ea74bd 100644
--- a/chrome/browser/ui/messages/android/BUILD.gn
+++ b/chrome/browser/ui/messages/android/BUILD.gn
@@ -34,6 +34,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/browser/util:java",
     "//components/browser_ui/styles/android:java",
     "//components/browser_ui/styles/android:java_resources",
diff --git a/chrome/browser/ui/page_info/page_info_unittest.cc b/chrome/browser/ui/page_info/page_info_unittest.cc
index 9d460a2..7b230de 100644
--- a/chrome/browser/ui/page_info/page_info_unittest.cc
+++ b/chrome/browser/ui/page_info/page_info_unittest.cc
@@ -364,7 +364,7 @@
 #endif
         EXPECT_EQ(normal, mid_sentence);
         break;
-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
       case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER:
         EXPECT_NE(normal, mid_sentence);
         EXPECT_EQ(base::ToLowerASCII(normal), base::ToLowerASCII(mid_sentence));
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
index 273231a..f9202b4 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -103,6 +103,10 @@
 // The default icon size used in the suggestion drop down.
 constexpr int kIconSize = 16;
 
+// The icon size used in the suggestion dropdown for displaying the Google
+// Password Manager icon in the Manager Passwords entry.
+constexpr int kGooglePasswordManagerIconSize = 20;
+
 // Popup items that use a leading icon instead of a trailing one.
 constexpr PopupItemId kItemTypesUsingLeadingIcons[] = {
     PopupItemId::POPUP_ITEM_ID_CLEAR_FORM,
@@ -159,9 +163,15 @@
 }
 
 std::unique_ptr<views::ImageView> ImageViewFromVectorIcon(
-    const gfx::VectorIcon& vector_icon) {
+    const gfx::VectorIcon& vector_icon,
+    int icon_size) {
   return std::make_unique<views::ImageView>(
-      ui::ImageModel::FromVectorIcon(vector_icon, ui::kColorIcon, kIconSize));
+      ui::ImageModel::FromVectorIcon(vector_icon, ui::kColorIcon, icon_size));
+}
+
+std::unique_ptr<views::ImageView> ImageViewFromVectorIcon(
+    const gfx::VectorIcon& vector_icon) {
+  return ImageViewFromVectorIcon(vector_icon, kIconSize);
 }
 
 std::unique_ptr<views::ImageView> GetIconImageViewByName(
@@ -217,7 +227,8 @@
   }
 
   if (icon_str == "googlePasswordManager") {
-    return ImageViewFromVectorIcon(GooglePasswordManagerVectorIcon());
+    return ImageViewFromVectorIcon(GooglePasswordManagerVectorIcon(),
+                                   kGooglePasswordManagerIconSize);
   }
 
 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
diff --git a/chrome/browser/ui/views/page_info/page_info_view_factory.cc b/chrome/browser/ui/views/page_info/page_info_view_factory.cc
index c6aefbb..e688a3b8 100644
--- a/chrome/browser/ui/views/page_info/page_info_view_factory.cc
+++ b/chrome/browser/ui/views/page_info/page_info_view_factory.cc
@@ -251,7 +251,7 @@
     case ContentSettingsType::AUTOMATIC_DOWNLOADS:
       icon = &vector_icons::kFileDownloadIcon;
       break;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
     case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER:
       icon = &vector_icons::kProtectedContentIcon;
       break;
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc
index 64fda4d4..6c35bfb 100644
--- a/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc
@@ -501,7 +501,7 @@
 }
 
 // ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER is ChromeOS only.
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
 IN_PROC_BROWSER_TEST_P(PermissionPromptBubbleViewBrowserTest,
                        InvokeUi_protected_media) {
   ShowAndVerifyUi();
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc
index 0799eaa..b216d7f7 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -955,6 +955,8 @@
                            gfx::Insets::VH(vertical_spacing, 0));
   }
   auto* form_view = view->AddChildView(std::make_unique<views::View>());
+  // Stretch `form_view` to fit the rest of bubble's width.
+  layout->SetFlexForView(form_view, 1);
   form_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kVertical, gfx::Insets(),
       vertical_spacing));
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view_browsertest.cc b/chrome/browser/ui/views/translate/translate_bubble_view_browsertest.cc
index 466576e..5766802 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view_browsertest.cc
@@ -194,7 +194,12 @@
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_F(TranslateBubbleVisualTest, InvokeUi_advanced) {
+IN_PROC_BROWSER_TEST_F(TranslateBubbleVisualTest, InvokeUi_before_translate) {
+  set_state(TranslateBubbleModel::ViewState::VIEW_STATE_BEFORE_TRANSLATE);
+  ShowAndVerifyUi();
+}
+
+IN_PROC_BROWSER_TEST_F(TranslateBubbleVisualTest, InvokeUi_select_source) {
   set_state(TranslateBubbleModel::ViewState::VIEW_STATE_SOURCE_LANGUAGE);
   ShowAndVerifyUi();
 }
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 884c7dcf..eb6d01b 100644
--- a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
+++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
@@ -30,6 +30,7 @@
 constexpr int kBubbleWidth = 375;
 constexpr int kDesiredAvatarSize = 40;
 constexpr int kPadding = 5;
+constexpr int kProgressBarHeight = 2;
 
 constexpr char kImageFetcherUmaClient[] = "FedCMAccountChooser";
 
@@ -283,9 +284,11 @@
     const content::IdentityRequestAccount& account) {
   SetTitle(l10n_util::GetStringUTF16(IDS_VERIFY_SHEET_TITLE));
   RemoveAllChildViews();
-  // TODO(npm): replace the basic views::Separator with a separator that has the
-  // loading animation.
-  AddChildView(std::make_unique<views::Separator>());
+  views::ProgressBar* progress_bar =
+      AddChildView(std::make_unique<views::ProgressBar>(kProgressBarHeight));
+  // Use an infinite animation: SetValue(-1).
+  progress_bar->SetValue(-1);
+  progress_bar->SetBackgroundColor(SK_ColorLTGRAY);
   AddChildView(CreateAccountRow(account, /*should_hover=*/false));
   SizeToContents();
   PreferredSizeChanged();
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc b/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc
index 6e29705..80374200 100644
--- a/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ui/views/hover_button.h"
+#include "chrome/browser/ui/views/webid/fake_delegate.h"
 #include "chrome/browser/ui/webid/identity_dialog_controller.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/views/chrome_views_test_base.h"
@@ -41,25 +42,6 @@
 
 }  // namespace
 
-class FakeDelegate : public AccountSelectionView::Delegate {
- public:
-  explicit FakeDelegate(content::WebContents* web_contents)
-      : web_contents_(web_contents) {}
-
-  ~FakeDelegate() override = default;
-
-  void OnAccountSelected(const Account& account) override {}
-
-  void OnDismiss(bool should_embargo) override {}
-
-  gfx::NativeView GetNativeView() override { return gfx::kNullNativeView; }
-
-  content::WebContents* GetWebContents() override { return web_contents_; }
-
- private:
-  content::WebContents* web_contents_;
-};
-
 class AccountSelectionBubbleViewTest : public ChromeViewsTestBase {
  public:
   AccountSelectionBubbleViewTest() = default;
@@ -102,9 +84,34 @@
     views::BubbleDialogDelegateView::CreateBubble(dialog_)->Show();
   }
 
-  void CheckAccountRow(views::View* view,
+  void CheckAccountRow(views::View* row,
                        std::u16string name,
-                       std::u16string email) {}
+                       std::u16string email) {
+    std::vector<views::View*> row_children = row->children();
+    ASSERT_EQ(row_children.size(), 2u);
+
+    // Check the image.
+    views::ImageView* image_view =
+        static_cast<views::ImageView*>(row_children[0]);
+    EXPECT_TRUE(image_view);
+
+    // Check the text shown.
+    views::View* text_view = row_children[1];
+    views::BoxLayout* layout_manager =
+        static_cast<views::BoxLayout*>(text_view->GetLayoutManager());
+    ASSERT_TRUE(layout_manager);
+    EXPECT_EQ(layout_manager->GetOrientation(),
+              views::BoxLayout::Orientation::kVertical);
+    std::vector<views::View*> text_view_children = text_view->children();
+    ASSERT_EQ(text_view_children.size(), 2u);
+    views::Label* name_view = static_cast<views::Label*>(text_view_children[0]);
+    ASSERT_TRUE(name_view);
+    EXPECT_EQ(name_view->GetText(), name);
+    views::Label* email_view =
+        static_cast<views::Label*>(text_view_children[1]);
+    ASSERT_TRUE(email_view);
+    EXPECT_EQ(email_view->GetText(), email);
+  }
 
   void SetUp() override {
     feature_list_.InitAndEnableFeature(features::kFedCm);
@@ -143,7 +150,6 @@
   scoped_refptr<network::SharedURLLoaderFactory>
       test_shared_url_loader_factory_;
   network::TestURLLoaderFactory test_url_loader_factory_;
-  // testing::NiceMock<MockEditAddressProfileDialogController> mock_controller_;
 };
 
 TEST_F(AccountSelectionBubbleViewTest, SingleAccount) {
@@ -165,28 +171,8 @@
   EXPECT_TRUE(separator);
   views::View* single_account_chooser = children[1];
   ASSERT_EQ(single_account_chooser->children().size(), 3u);
-  views::View* account_row = single_account_chooser->children()[0];
-  std::vector<views::View*> row_children = account_row->children();
-  ASSERT_EQ(row_children.size(), 2u);
-  views::ImageView* image_view =
-      static_cast<views::ImageView*>(row_children[0]);
-  EXPECT_TRUE(image_view);
 
-  // Check the text shown.
-  views::View* text_view = row_children[1];
-  views::BoxLayout* layout_manager =
-      static_cast<views::BoxLayout*>(text_view->GetLayoutManager());
-  ASSERT_TRUE(layout_manager);
-  EXPECT_EQ(layout_manager->GetOrientation(),
-            views::BoxLayout::Orientation::kVertical);
-  std::vector<views::View*> text_view_children = text_view->children();
-  ASSERT_EQ(text_view_children.size(), 2u);
-  views::Label* name_view = static_cast<views::Label*>(text_view_children[0]);
-  ASSERT_TRUE(name_view);
-  EXPECT_EQ(name_view->GetText(), u"name");
-  views::Label* email_view = static_cast<views::Label*>(text_view_children[1]);
-  ASSERT_TRUE(email_view);
-  EXPECT_EQ(email_view->GetText(), u"email");
+  CheckAccountRow(single_account_chooser->children()[0], u"name", u"email");
 
   // Check the "Continue as" button.
   views::MdTextButton* button =
@@ -306,26 +292,8 @@
   ASSERT_EQ(single_account_chooser->children().size(), 3u);
   views::View* single_account_row = single_account_chooser->children()[0];
   std::vector<views::View*> row_children = single_account_row->children();
-  ASSERT_EQ(row_children.size(), 2u);
-  views::ImageView* image_view =
-      static_cast<views::ImageView*>(row_children[0]);
-  EXPECT_TRUE(image_view);
 
-  // Check the text shown.
-  views::View* text_view = row_children[1];
-  views::BoxLayout* layout_manager =
-      static_cast<views::BoxLayout*>(text_view->GetLayoutManager());
-  ASSERT_TRUE(layout_manager);
-  EXPECT_EQ(layout_manager->GetOrientation(),
-            views::BoxLayout::Orientation::kVertical);
-  std::vector<views::View*> text_view_children = text_view->children();
-  ASSERT_EQ(text_view_children.size(), 2u);
-  views::Label* name_view = static_cast<views::Label*>(text_view_children[0]);
-  ASSERT_TRUE(name_view);
-  EXPECT_EQ(name_view->GetText(), u"name1");
-  views::Label* email_view = static_cast<views::Label*>(text_view_children[1]);
-  ASSERT_TRUE(email_view);
-  EXPECT_EQ(email_view->GetText(), u"email1");
+  CheckAccountRow(single_account_row, u"name1", u"email1");
 
   // Check the "Continue as" button.
   views::MdTextButton* button =
@@ -351,4 +319,11 @@
   EXPECT_FALSE(dialog()->GetOkButton());
   EXPECT_FALSE(dialog()->GetCancelButton());
   EXPECT_EQ(dialog()->GetWindowTitle(), kTitleSigningIn);
+
+  ASSERT_EQ(dialog()->children().size(), 2u);
+  views::ProgressBar* progress_bar =
+      static_cast<views::ProgressBar*>(dialog()->children()[0]);
+  ASSERT_TRUE(progress_bar);
+
+  CheckAccountRow(dialog()->children()[1], u"name1", u"email1");
 }
diff --git a/chrome/browser/ui/views/webid/fake_delegate.cc b/chrome/browser/ui/views/webid/fake_delegate.cc
new file mode 100644
index 0000000..afec245
--- /dev/null
+++ b/chrome/browser/ui/views/webid/fake_delegate.cc
@@ -0,0 +1,13 @@
+// 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/webid/fake_delegate.h"
+
+gfx::NativeView FakeDelegate::GetNativeView() {
+  return gfx::kNullNativeView;
+}
+
+content::WebContents* FakeDelegate::GetWebContents() {
+  return web_contents_;
+}
diff --git a/chrome/browser/ui/views/webid/fake_delegate.h b/chrome/browser/ui/views/webid/fake_delegate.h
new file mode 100644
index 0000000..c68ee89
--- /dev/null
+++ b/chrome/browser/ui/views/webid/fake_delegate.h
@@ -0,0 +1,30 @@
+// 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_VIEWS_WEBID_FAKE_DELEGATE_H_
+#define CHROME_BROWSER_UI_VIEWS_WEBID_FAKE_DELEGATE_H_
+
+#include "chrome/browser/ui/webid/account_selection_view.h"
+#include "ui/gfx/native_widget_types.h"
+
+class FakeDelegate : public AccountSelectionView::Delegate {
+ public:
+  explicit FakeDelegate(content::WebContents* web_contents)
+      : web_contents_(web_contents) {}
+
+  ~FakeDelegate() override = default;
+
+  void OnAccountSelected(const Account& account) override {}
+
+  void OnDismiss(bool should_embargo) override {}
+
+  // AccountSelectionView::Delegate
+  gfx::NativeView GetNativeView() override;
+  content::WebContents* GetWebContents() override;
+
+ private:
+  content::WebContents* web_contents_;
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_WEBID_FAKE_DELEGATE_H_
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
index 7377cc2..bad1dc9 100644
--- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
+++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
@@ -33,7 +33,8 @@
 
 FedCmAccountSelectionView::FedCmAccountSelectionView(
     AccountSelectionView::Delegate* delegate)
-    : AccountSelectionView(delegate) {}
+    : AccountSelectionView(delegate),
+      content::WebContentsObserver(delegate->GetWebContents()) {}
 
 FedCmAccountSelectionView::~FedCmAccountSelectionView() {
   if (bubble_widget_) {
@@ -63,3 +64,25 @@
                        ->GetWeakPtr();
   bubble_widget_->Show();
 }
+
+void FedCmAccountSelectionView::OnVisibilityChanged(
+    content::Visibility visibility) {
+  if (!bubble_widget_)
+    return;
+
+  if (visibility == content::Visibility::VISIBLE) {
+    bubble_widget_->Show();
+  } else {
+    bubble_widget_->Hide();
+  }
+}
+
+void FedCmAccountSelectionView::RenderViewHostChanged(
+    content::RenderViewHost* old_host,
+    content::RenderViewHost* new_host) {
+  // Close the bubble when the user navigates within the same tab.
+  if (bubble_widget_) {
+    bubble_widget_->Close();
+    bubble_widget_ = nullptr;
+  }
+}
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h
index 9c4ca350..81542f8 100644
--- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h
+++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h
@@ -8,11 +8,13 @@
 #include "chrome/browser/ui/webid/account_selection_view.h"
 
 #include "chrome/browser/ui/views/webid/account_selection_bubble_view.h"
+#include "content/public/browser/web_contents_observer.h"
 
 // Provides an implementation of the AccountSelectionView interface on desktop,
 // which creates the AccountSelectionBubbleView dialog to display the FedCM
 // account chooser to the user.
-class FedCmAccountSelectionView : public AccountSelectionView {
+class FedCmAccountSelectionView : public AccountSelectionView,
+                                  content::WebContentsObserver {
  public:
   explicit FedCmAccountSelectionView(AccountSelectionView::Delegate* delegate);
   ~FedCmAccountSelectionView() override;
@@ -25,7 +27,14 @@
             const content::ClientIdData& client_data,
             Account::SignInMode sign_in_mode) override;
 
- private:
+  // content::WebContentsObserver
+  void OnVisibilityChanged(content::Visibility visibility) override;
+  void RenderViewHostChanged(content::RenderViewHost* old_host,
+                             content::RenderViewHost* new_host) override;
+
+ protected:
+  friend class FedCmAccountSelectionViewBrowserTest;
+
   base::WeakPtr<views::Widget> bubble_widget_;
 };
 
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_browsertest.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_browsertest.cc
new file mode 100644
index 0000000..a6946f1
--- /dev/null
+++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_browsertest.cc
@@ -0,0 +1,98 @@
+// 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/webid/fedcm_account_selection_view_desktop.h"
+
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/browser/ui/views/webid/fake_delegate.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/views/chrome_views_test_base.h"
+#include "content/public/common/content_features.h"
+#include "content/public/test/browser_test.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+class FedCmAccountSelectionViewBrowserTest : public DialogBrowserTest {
+ public:
+  FedCmAccountSelectionViewBrowserTest() {
+    feature_list_.InitAndEnableFeature(features::kFedCm);
+  }
+
+  void PreShow() override {
+    delegate_ = std::make_unique<FakeDelegate>(
+        browser()->tab_strip_model()->GetActiveWebContents());
+    account_selection_view_ =
+        std::make_unique<FedCmAccountSelectionView>(delegate());
+  }
+
+  void ShowUi(const std::string& name) override {
+    std::vector<const content::IdentityRequestAccount> accounts = {
+        {"id", "email", "name", "given_name", GURL::EmptyGURL()}};
+    content::IdentityProviderMetadata idp_metadata;
+    content::ClientIdData client_data(GURL::EmptyGURL(), GURL::EmptyGURL());
+    account_selection_view()->Show("rp-example.com", "idp-example.com",
+                                   accounts, idp_metadata, client_data,
+                                   Account::SignInMode::kExplicit);
+  }
+
+  void Show() {
+    PreShow();
+    ShowUi("");
+  }
+
+  base::WeakPtr<views::Widget> GetBubble() {
+    return account_selection_view_->bubble_widget_;
+  }
+
+  FakeDelegate* delegate() { return delegate_.get(); }
+
+  FedCmAccountSelectionView* account_selection_view() {
+    return account_selection_view_.get();
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+  std::unique_ptr<FakeDelegate> delegate_;
+  std::unique_ptr<FedCmAccountSelectionView> account_selection_view_;
+};
+
+IN_PROC_BROWSER_TEST_F(FedCmAccountSelectionViewBrowserTest, ShowAndVerifyUi) {
+  ShowAndVerifyUi();
+}
+
+IN_PROC_BROWSER_TEST_F(FedCmAccountSelectionViewBrowserTest, Hide) {
+  Show();
+  ASSERT_TRUE(GetBubble());
+  EXPECT_TRUE(GetBubble()->IsVisible());
+  browser()->tab_strip_model()->GetActiveWebContents()->WasHidden();
+  // The bubble should be closed after the WebContents is Hidden.
+  ASSERT_TRUE(GetBubble());
+  EXPECT_FALSE(GetBubble()->IsVisible());
+}
+
+IN_PROC_BROWSER_TEST_F(FedCmAccountSelectionViewBrowserTest, NavigateAway) {
+  Show();
+  ASSERT_TRUE(GetBubble());
+  EXPECT_TRUE(GetBubble()->IsVisible());
+  // Navigate away to a real URL, otherwise it does not seem to work.
+  ASSERT_TRUE(
+      ui_test_utils::NavigateToURL(browser(), GURL("https://www.google.com")));
+  // The bubble should be closed after the browser navigates away from the page.
+  EXPECT_FALSE(GetBubble());
+}
+
+IN_PROC_BROWSER_TEST_F(FedCmAccountSelectionViewBrowserTest, ReShow) {
+  Show();
+  browser()->tab_strip_model()->GetActiveWebContents()->WasHidden();
+  // The bubble should be closed after the WebContents is Hidden.
+  ASSERT_TRUE(GetBubble());
+  EXPECT_FALSE(GetBubble()->IsVisible());
+
+  browser()->tab_strip_model()->GetActiveWebContents()->WasShown();
+  // The bubble should be reshown after the WebContents is Visible.
+  ASSERT_TRUE(GetBubble());
+  EXPECT_TRUE(GetBubble()->IsVisible());
+}
diff --git a/chrome/browser/ui/webui/history_clusters/history_clusters.mojom b/chrome/browser/ui/webui/history_clusters/history_clusters.mojom
index 1726e12..c2fe150 100644
--- a/chrome/browser/ui/webui/history_clusters/history_clusters.mojom
+++ b/chrome/browser/ui/webui/history_clusters/history_clusters.mojom
@@ -131,6 +131,10 @@
   // The ClustersBrowserProxy singleton calls this when it's first initialized.
   SetPage(pending_remote<Page> page);
 
+  // Notifies the native handler whether the History Clusters Page is selected.
+  // Called when the WebUI page is loaded, and when the user switches tabs.
+  NotifyHistoryClustersSelected(bool history_clusters_selected);
+
   // Toggles the visibility of the History Clusters. The returned Promise echos
   // the given value for `visible`. The page uses the returned value to update
   // its state once the request is fulfilled by the browser.
diff --git a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
index f2b8b5c..af0b0df 100644
--- a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
+++ b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
@@ -15,6 +15,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
+#include "base/timer/elapsed_timer.h"
 #include "chrome/browser/history_clusters/history_clusters_metrics_logger.h"
 #include "chrome/browser/history_clusters/history_clusters_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -221,6 +222,18 @@
   return result_mojom;
 }
 
+// An internal only class used to track WebUI lifetime.
+class HistoryClustersHandler::ScopedElapsedTimer {
+ public:
+  ~ScopedElapsedTimer() {
+    base::UmaHistogramLongTimes100("History.Clusters.WebUISessionDuration",
+                                   timer_.Elapsed());
+  }
+
+ private:
+  base::ElapsedTimer timer_;
+};
+
 HistoryClustersHandler::HistoryClustersHandler(
     mojo::PendingReceiver<mojom::PageHandler> pending_page_handler,
     Profile* profile,
@@ -251,6 +264,17 @@
   std::move(callback).Run(visible);
 }
 
+void HistoryClustersHandler::NotifyHistoryClustersSelected(
+    bool history_clusters_selected) {
+  if (history_clusters_selected) {
+    if (!webui_session_duration_) {
+      webui_session_duration_ = std::make_unique<ScopedElapsedTimer>();
+    }
+  } else {
+    webui_session_duration_.reset();
+  }
+}
+
 void HistoryClustersHandler::StartQueryClusters(const std::string& query) {
   if (!query.empty()) {
     // If the query string is not empty, we assume that this clusters query
diff --git a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.h b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.h
index 6b986a68..bc15bcf 100644
--- a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.h
+++ b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.h
@@ -59,6 +59,7 @@
   void SetPage(mojo::PendingRemote<mojom::Page> pending_page) override;
   void ToggleVisibility(bool visible,
                         ToggleVisibilityCallback callback) override;
+  void NotifyHistoryClustersSelected(bool history_clusters_selected) override;
   void StartQueryClusters(const std::string& query) override;
   void LoadMoreClusters(const std::string& query) override;
   void RemoveVisits(std::vector<mojom::URLVisitPtr> visits,
@@ -69,6 +70,9 @@
   void OnDebugMessage(const std::string& message) override;
 
  private:
+  // An internal only class used to track WebUI lifetime.
+  class ScopedElapsedTimer;
+
   // Called with the result of querying clusters. Subsequently, `query_result`
   // is sent to the JS to update the UI.
   void OnClustersQueryResult(mojom::QueryResultPtr query_result);
@@ -92,6 +96,11 @@
   // Encapsulates the currently loaded clusters state on the page.
   std::unique_ptr<QueryClustersState> query_clusters_state_;
 
+  // A page lifetime timer used to record how long the user spends on the WebUI.
+  // This is specifically not constructed in the class constructor because the
+  // user may be looking at a different tab.
+  std::unique_ptr<ScopedElapsedTimer> webui_session_duration_;
+
   base::WeakPtrFactory<HistoryClustersHandler> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_default_unittest.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_default_unittest.cc
index 364975c..7d3a6788 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_default_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_default_unittest.cc
@@ -105,8 +105,15 @@
   void SetUp() override {
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
     // Choose between running with local test runner or via a service.
-    feature_list_.InitWithFeatureState(features::kEnableOopPrintDrivers,
-                                       UseService());
+    if (UseService()) {
+      feature_list_.InitAndEnableFeatureWithParameters(
+          features::kEnableOopPrintDrivers,
+          {{ features::kEnableOopPrintDriversSandbox.name,
+             "true" }});
+    } else {
+      feature_list_.InitWithFeatureState(features::kEnableOopPrintDrivers,
+                                         false);
+    }
 #endif
 
     TestingProfile::Builder builder;
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 4e429b9c..b584817 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -2242,7 +2242,7 @@
      IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_BLOCKED},
     {"siteSettingsProtectedContentBlockedSubLabel",
      IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_BLOCKED_SUB_LABEL},
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
     {"siteSettingsProtectedContentIdentifiersExplanation",
      IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_IDENTIFIERS_EXPLANATION},
     {"siteSettingsProtectedContentEnableIdentifiers",
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chrome/browser/ui/webui/settings/site_settings_helper.cc
index fbeae28..9f16cc4b6 100644
--- a/chrome/browser/ui/webui/settings/site_settings_helper.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_helper.cc
@@ -439,7 +439,7 @@
       ContentSettingsType::MIXEDSCRIPT,
       ContentSettingsType::NOTIFICATIONS,
       ContentSettingsType::POPUPS,
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
       ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
 #endif
       ContentSettingsType::SENSORS,
diff --git a/chrome/browser/uid/android/BUILD.gn b/chrome/browser/uid/android/BUILD.gn
index d724b05..5081bc3b 100644
--- a/chrome/browser/uid/android/BUILD.gn
+++ b/chrome/browser/uid/android/BUILD.gn
@@ -30,6 +30,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/util:java",
     "//chrome/test/android:chrome_java_test_support",
diff --git a/chrome/browser/user_education/BUILD.gn b/chrome/browser/user_education/BUILD.gn
index d2b95be8..b70ca65 100644
--- a/chrome/browser/user_education/BUILD.gn
+++ b/chrome/browser/user_education/BUILD.gn
@@ -36,6 +36,7 @@
   deps = [
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/browser/feature_engagement:java",
     "//chrome/browser/flags:java",
     "//chrome/browser/profiles/android:java",
diff --git a/chrome/browser/util/BUILD.gn b/chrome/browser/util/BUILD.gn
index f7e15af..46f4d752 100644
--- a/chrome/browser/util/BUILD.gn
+++ b/chrome/browser/util/BUILD.gn
@@ -17,6 +17,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/util/android:java",
     "//components/embedder_support/android:util_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/chrome/browser/video_tutorials/BUILD.gn b/chrome/browser/video_tutorials/BUILD.gn
index fb3f75f..8523c7e 100644
--- a/chrome/browser/video_tutorials/BUILD.gn
+++ b/chrome/browser/video_tutorials/BUILD.gn
@@ -133,6 +133,7 @@
     deps = [
       ":java",
       "//base:base_java",
+      "//build/android:build_java",
       "//components/image_fetcher:java",
       "//third_party/androidx:androidx_annotation_annotation_java",
       "//third_party/gif_player:gif_player_java",
diff --git a/chrome/browser/video_tutorials/internal/BUILD.gn b/chrome/browser/video_tutorials/internal/BUILD.gn
index 8c4dac1..db37ccde6 100644
--- a/chrome/browser/video_tutorials/internal/BUILD.gn
+++ b/chrome/browser/video_tutorials/internal/BUILD.gn
@@ -88,6 +88,7 @@
     deps = [
       ":java_resources",
       "//base:base_java",
+      "//build/android:build_java",
       "//chrome/browser/flags:java",
       "//chrome/browser/profiles/android:java",
       "//chrome/browser/video_tutorials:java",
@@ -184,6 +185,7 @@
       ":java_resources",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//chrome/browser/flags:java",
       "//chrome/browser/video_tutorials:java",
       "//chrome/browser/video_tutorials:test_support_java",
diff --git a/chrome/browser/webauthn/android/BUILD.gn b/chrome/browser/webauthn/android/BUILD.gn
index 5924d6e..8b48b6b 100644
--- a/chrome/browser/webauthn/android/BUILD.gn
+++ b/chrome/browser/webauthn/android/BUILD.gn
@@ -13,6 +13,7 @@
     ":java_resources",
     ":jni_headers",
     "//base:base_java",
+    "//build/android:build_java",
     "//chrome/android:chrome_app_java_resources",
     "//chrome/android/modules/cablev2_authenticator/public:java",
     "//chrome/browser/notifications:java",
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 1b735f5e..7576f6f 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1651060496-818a36840f8a9d89b6df6df056d7a85fcf6e6dda.profdata
+chrome-mac-arm-main-1651082056-ee84e0d08937274b8fcf6d2e3f1e5a736a21e20a.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 7efa92139..993d0370 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1651060496-a0e64210b38fb339daec85659543079a0d9a9b4c.profdata
+chrome-mac-main-1651082056-9525af8a99e86002e967da38f208f8a9ee9ca3cd.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index daedd92..37fa4ee5 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1651071352-ff02035d1a3d0266c8b03d30ecc1a91725b14c86.profdata
+chrome-win32-main-1651082056-f661d0c51d9c8f26a24b66c9cdaca610b95032d0.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index b2a4d87..4d49ef7 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1651071352-26cb4549f0df346cb9bdead7ab8245a4777ec93f.profdata
+chrome-win64-main-1651082056-1448b7ec8f1feed2356cf67d96f3b30a375b00c0.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 62f71ec..9c0eb8f 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1048,6 +1048,7 @@
     deps = [
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
       "//chrome/android:base_module_java",
       "//chrome/android:chrome_all_java",
@@ -2151,6 +2152,9 @@
       "../browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc",
       "../browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc",
       "../browser/ui/views/webauthn/webauthn_icon_interactive_uitest.cc",
+      "../browser/ui/views/webid/fake_delegate.cc",
+      "../browser/ui/views/webid/fake_delegate.h",
+      "../browser/ui/views/webid/fedcm_account_selection_view_desktop_browsertest.cc",
       "../browser/ui/views/webview_accessibility_browsertest.cc",
       "../browser/ui/web_applications/app_browser_controller_browsertest.cc",
       "../browser/ui/web_applications/create_shortcut_browsertest.cc",
@@ -5095,7 +5099,6 @@
     "../browser/performance_manager/decorators/process_priority_aggregator_unittest.cc",
     "../browser/performance_manager/mechanisms/page_freezer_unittest.cc",
     "../browser/performance_manager/metrics/memory_pressure_metrics_unittest.cc",
-    "../browser/performance_manager/observers/isolation_context_metrics_unittest.cc",
     "../browser/performance_manager/policies/page_freezing_policy_unittest.cc",
     "../browser/performance_manager/policies/working_set_trimmer_policy_unittest.cc",
     "../browser/performance_manager/test_support/page_aggregator.cc",
@@ -5335,16 +5338,6 @@
     ]
   }
 
-  if (enable_paint_preview) {
-    sources += [
-      "../browser/paint_preview/services/paint_preview_tab_service_unittest.cc",
-    ]
-  }
-
-  if (enable_side_search) {
-    sources += [ "../browser/page_load_metrics/observers/side_search_page_load_metrics_observer_unittest.cc" ]
-  }
-
   if (is_chromeos) {
     sources += [
       "../browser/apps/intent_helper/metrics/intent_handling_metrics_unittest.cc",
@@ -5400,11 +5393,6 @@
     ]
   }
 
-  if (toolkit_views) {
-    # Test accessibility checks that audit any UI opened in a browser test.
-    sources += [ "views/accessibility_checker_unittest.cc" ]
-  }
-
   if (enable_chrome_notifications) {
     sources += [
       "../browser/notifications/notification_system_observer_unittest.cc",
@@ -5451,13 +5439,17 @@
 
   if (enable_webui_tab_strip) {
     sources += [
+      "../browser/ui/views/frame/webui_tab_strip_container_view_unittest.cc",
       "../browser/ui/views/toolbar/webui_tab_counter_button_unittest.cc",
       "../browser/ui/webui/tab_strip/tab_strip_page_handler_unittest.cc",
+      "../browser/ui/webui/tab_strip/tab_strip_ui_layout_unittest.cc",
+      "../browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc",
     ]
   }
 
   if (enable_side_search) {
     sources += [
+      "../browser/page_load_metrics/observers/side_search_page_load_metrics_observer_unittest.cc",
       "../browser/ui/side_search/side_search_side_contents_helper_unittest.cc",
       "../browser/ui/side_search/side_search_tab_contents_helper_unittest.cc",
     ]
@@ -6049,6 +6041,9 @@
   }
 
   if (enable_paint_preview) {
+    sources += [
+      "../browser/paint_preview/services/paint_preview_tab_service_unittest.cc",
+    ]
     deps += [ "//chrome/browser/paint_preview:services" ]
   }
 
@@ -6223,6 +6218,7 @@
 
     deps += [
       "//base:base_java",
+      "//build/android:build_java",
       "//chrome:chrome_android_core",
       "//chrome/android:chrome_apk_paks",
       "//chrome/android:chrome_java",
@@ -6628,6 +6624,8 @@
       "../browser/ui/views/passwords/password_save_update_view_unittest.cc",
       "../browser/ui/views/passwords/post_save_compromised_bubble_view_unittest.cc",
       "../browser/ui/views/webid/account_selection_bubble_view_unittest.cc",
+      "../browser/ui/views/webid/fake_delegate.cc",
+      "../browser/ui/views/webid/fake_delegate.h",
       "../browser/ui/web_applications/app_browser_controller_unittest.cc",
       "../browser/ui/web_applications/share_target_utils_unittest.cc",
       "../browser/ui/web_applications/web_app_launch_manager_unittest.cc",
@@ -8261,6 +8259,9 @@
   }
 
   if (toolkit_views) {
+    # Test accessibility checks that audit any UI opened in a browser test.
+    sources += [ "views/accessibility_checker_unittest.cc" ]
+
     deps += [
       "//chrome:unit_tests_pak",
       "//chrome/browser/ui/tabs:tab_enums",
@@ -8496,14 +8497,6 @@
         [ "../common/media/component_widevine_cdm_hint_file_linux_unittest.cc" ]
   }
 
-  if (enable_webui_tab_strip) {
-    sources += [
-      "../browser/ui/views/frame/webui_tab_strip_container_view_unittest.cc",
-      "../browser/ui/webui/tab_strip/tab_strip_ui_layout_unittest.cc",
-      "../browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc",
-    ]
-  }
-
   # This target gets pulled in in Chromecast builds, even though it doesn't get
   # built or used there. The below files cause "gn check" failures in ways that
   # would be resolvable only by adding "nogncheck" on the includes in question.
@@ -9544,6 +9537,7 @@
     testonly = true
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//chrome/android:chrome_all_java",
       "//chrome/browser/profiles/android:java",
       "//chrome/test/android:chrome_java_test_support",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 3666013..1604c11 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -41,6 +41,7 @@
     ":chrome_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/ui/android/appmenu/test:test_support_java",
     "//third_party/android_deps:guava_android_java",
@@ -100,6 +101,7 @@
     ":chrome_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/tab:java",
@@ -136,6 +138,7 @@
     ":chrome_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/tab:java",
@@ -170,6 +173,7 @@
     ":chrome_java_test_pagecontroller",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//chrome/android/webapk/libs/client:client_java",
     "//chrome/android/webapk/libs/runtime_library:runtime_library_javatests",
@@ -229,6 +233,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//third_party/ub-uiautomator:ub_uiautomator_java",
   ]
 }
@@ -307,6 +312,7 @@
     "$google_play_services_package:google_play_services_basement_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:base_module_java",
     "//chrome/android:chrome_java",
     "//chrome/browser/android/browserservices/constants:java",
diff --git a/chrome/test/data/notifications/notification_permission_checker.html b/chrome/test/data/notifications/notification_permission_checker.html
index d11336e..fa4693fb 100644
--- a/chrome/test/data/notifications/notification_permission_checker.html
+++ b/chrome/test/data/notifications/notification_permission_checker.html
@@ -39,9 +39,13 @@
 
 async function requestPushPermission() {
   let sw = await getServiceWorkerRegistration();
+  let dummy_application_server_key = new Array(65);
+  dummy_application_server_key[0] = 0x04;
   let options = {
     userVisibleOnly: true,
-    applicationServerKey: btoa('0123456789').replaceAll('=', ''),
+    applicationServerKey: 
+      new TextEncoder().encode(
+        String.fromCharCode(...dummy_application_server_key)),
   };
   sw.pushManager.subscribe(options)
       .then(sub => sendResultToTest(sub.toJSON()))
diff --git a/chrome/test/data/webui/chromeos/personalization_app/google_photos_albums_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/google_photos_albums_element_test.ts
index 3c7ff0e..ef63970 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/google_photos_albums_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/google_photos_albums_element_test.ts
@@ -21,14 +21,6 @@
   let wallpaperProvider: TestWallpaperProvider;
 
   /**
-   * Returns the match for |selector| in |googlePhotosAlbumsElement|'s shadow
-   * DOM.
-   */
-  function querySelector(selector: string): Element|null {
-    return googlePhotosAlbumsElement!.shadowRoot!.querySelector(selector);
-  }
-
-  /**
    * Returns all matches for |selector| in |googlePhotosAlbumsElement|'s shadow
    * DOM.
    */
@@ -189,7 +181,13 @@
     const albumSelector = `${selector}:not([placeholder])`;
     const placeholderSelector = `${selector}[placeholder]`;
     assertEquals(querySelectorAll(albumSelector)!.length, 0);
-    assertNotEquals(querySelectorAll(placeholderSelector)!.length, 0);
+    const placeholderEls = querySelectorAll(placeholderSelector);
+    assertNotEquals(placeholderEls!.length, 0);
+
+    // Placeholders should be aria-labeled.
+    placeholderEls!.forEach(placeholderEl => {
+      assertEquals(placeholderEl.getAttribute('aria-label'), 'Loading');
+    });
 
     // Mock singleton |PersonalizationRouter|.
     const router = TestBrowserProxy.fromClass(PersonalizationRouter);
@@ -202,7 +200,7 @@
     };
 
     // Clicking a placeholder should do nothing.
-    (querySelector(placeholderSelector) as HTMLElement).click();
+    (placeholderEls![0] as HTMLElement).click();
     await new Promise<void>(resolve => setTimeout(resolve));
     assertEquals(selectedGooglePhotosAlbum, undefined);
 
@@ -213,11 +211,17 @@
 
     // Only albums should be present.
     await waitAfterNextRender(googlePhotosAlbumsElement);
-    assertNotEquals(querySelectorAll(albumSelector)!.length, 0);
+    const albumEls = querySelectorAll(albumSelector);
+    assertNotEquals(albumEls!.length, 0);
     assertEquals(querySelectorAll(placeholderSelector)!.length, 0);
 
+    // Albums should be aria-labeled.
+    albumEls!.forEach((albumEl, i) => {
+      assertEquals(albumEl.getAttribute('aria-label'), albums[i]!.title);
+    });
+
     // Clicking an album should do something.
-    (querySelector(albumSelector) as HTMLElement).click();
+    (albumEls![0] as HTMLElement).click();
     assertEquals(selectedGooglePhotosAlbum, albums[0]);
   });
 
diff --git a/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts
index 1250c5b..0455ff2d 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts
@@ -20,15 +20,6 @@
   let wallpaperProvider: TestWallpaperProvider;
 
   /**
-   * Returns the match for |selector| in |googlePhotosPhotosByAlbumIdElement|'s
-   * shadow DOM.
-   */
-  function querySelector(selector: string): Element|null {
-    return googlePhotosPhotosByAlbumIdElement!.shadowRoot!.querySelector(
-        selector);
-  }
-
-  /**
    * Returns all matches for |selector| in
    * |googlePhotosPhotosByAlbumIdElement|'s shadow DOM.
    */
@@ -415,11 +406,17 @@
     googlePhotosPhotosByAlbumIdElement.setAttribute('album-id', album.id);
     await waitAfterNextRender(googlePhotosPhotosByAlbumIdElement);
     assertEquals(querySelectorAll(photoSelector)!.length, 0);
-    assertNotEquals(querySelectorAll(placeholderSelector)!.length, 0);
+    const placeholderEls = querySelectorAll(placeholderSelector);
+    assertNotEquals(placeholderEls!.length, 0);
+
+    // Placeholders should be aria-labeled.
+    placeholderEls!.forEach(placeholderEl => {
+      assertEquals(placeholderEl.getAttribute('aria-label'), 'Loading');
+    });
 
     // Clicking a placeholder should do nothing.
     const clickHandler = 'selectGooglePhotosPhoto';
-    (querySelector(placeholderSelector) as HTMLElement).click();
+    (placeholderEls![0] as HTMLElement).click();
     await new Promise<void>(resolve => setTimeout(resolve));
     assertEquals(wallpaperProvider.getCallCount(clickHandler), 0);
 
@@ -433,11 +430,17 @@
 
     // Only photos should be present.
     await waitAfterNextRender(googlePhotosPhotosByAlbumIdElement);
-    assertNotEquals(querySelectorAll(photoSelector)!.length, 0);
+    const photoEls = querySelectorAll(photoSelector);
+    assertNotEquals(photoEls!.length, 0);
     assertEquals(querySelectorAll(placeholderSelector)!.length, 0);
 
+    // Photos should be aria-labeled.
+    photoEls!.forEach((photoEl, i) => {
+      assertEquals(photoEl.getAttribute('aria-label'), photos[i]!.name);
+    });
+
     // Clicking a photo should do something.
-    (querySelector(photoSelector) as HTMLElement).click();
+    (photoEls![0] as HTMLElement).click();
     assertEquals(
         await wallpaperProvider.whenCalled(clickHandler), photos[0]!.id);
   });
diff --git a/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_element_test.ts
index fac94e4..1e3142e 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_element_test.ts
@@ -414,11 +414,17 @@
     const photoSelector = `${selector}:not([placeholder])`;
     const placeholderSelector = `${selector}[placeholder]`;
     assertEquals(querySelectorAll(photoSelector)!.length, 0);
-    assertNotEquals(querySelectorAll(placeholderSelector)!.length, 0);
+    const placeholderEls = querySelectorAll(placeholderSelector);
+    assertNotEquals(placeholderEls!.length, 0);
+
+    // Placeholders should be aria-labeled.
+    placeholderEls!.forEach(placeholderEl => {
+      assertEquals(placeholderEl.getAttribute('aria-label'), 'Loading');
+    });
 
     // Clicking a placeholder should do nothing.
     const clickHandler = 'selectGooglePhotosPhoto';
-    (querySelector(placeholderSelector) as HTMLElement).click();
+    (placeholderEls![0] as HTMLElement).click();
     await new Promise<void>(resolve => setTimeout(resolve));
     assertEquals(wallpaperProvider.getCallCount(clickHandler), 0);
 
@@ -429,11 +435,17 @@
 
     // Only photos should be present.
     await waitAfterNextRender(googlePhotosPhotosElement);
-    assertNotEquals(querySelectorAll(photoSelector)!.length, 0);
+    const photoEls = querySelectorAll(photoSelector);
+    assertNotEquals(photoEls!.length, 0);
     assertEquals(querySelectorAll(placeholderSelector)!.length, 0);
 
+    // Photos should be aria-labeled.
+    photoEls!.forEach((photoEl, i) => {
+      assertEquals(photoEl.getAttribute('aria-label'), photos[i]!.name);
+    });
+
     // Clicking a photo should do something.
-    (querySelector(photoSelector) as HTMLElement).click();
+    (photoEls![0] as HTMLElement).click();
     assertEquals(
         await wallpaperProvider.whenCalled(clickHandler), photos[0]!.id);
   });
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_browsertest.js b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_browsertest.js
index dc788a72..9db30a0a 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_browsertest.js
+++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_component_browsertest.js
@@ -32,8 +32,8 @@
  ['AmbientSubpageTest', 'ambient_subpage_element_test.js'],
  ['AvatarCameraTest', 'avatar_list_element_test.js'],
  ['AvatarListTest', 'avatar_list_element_test.js'],
- ['GooglePhotosAlbums', 'google_photos_albums_element_test.js'],
- ['GooglePhotosCollection', 'google_photos_collection_element_test.js'],
+ ['GooglePhotosAlbumsTest', 'google_photos_albums_element_test.js'],
+ ['GooglePhotosCollectionTest', 'google_photos_collection_element_test.js'],
  [
    'GooglePhotosPhotosByAlbumIdTest',
    'google_photos_photos_by_album_id_element_test.js'
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.js b/chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.js
index 0b0fedf..99328c1 100644
--- a/chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.js
@@ -222,7 +222,7 @@
   });
 
   test(
-      'setting isSmartLockSignInRemoved flat removes SmartLock subpage route',
+      'setting isSmartLockSignInRemoved flag removes SmartLock subpage route',
       function() {
         multideviceSubpage.remove();
         loadTimeData.overrideValues({'isSmartLockSignInRemoved': true});
diff --git a/chrome/test/data/webui/settings/chromeos/os_sync_controls_test.js b/chrome/test/data/webui/settings/chromeos/os_sync_controls_test.js
index 107c8f5..506e063 100644
--- a/chrome/test/data/webui/settings/chromeos/os_sync_controls_test.js
+++ b/chrome/test/data/webui/settings/chromeos/os_sync_controls_test.js
@@ -156,6 +156,21 @@
 
     // Select "Customize sync" instead of "Sync everything".
     customizeSync.click();
+    // Disable "Apps".
+    syncControls.$.osAppsControl.click();
+    const prefs = await browserProxy.whenCalled('setOsSyncDatatypes');
+
+    const expectedPrefs = getSyncAllPrefs();
+    expectedPrefs.syncAllOsTypes = false;
+    expectedPrefs.osAppsSynced = false;
+    assertEquals(JSON.stringify(expectedPrefs), JSON.stringify(prefs));
+  });
+
+  test('DisablingSettingsAlsoDisablesWallpaper', async function() {
+    setupSync();
+
+    // Select "Customize sync" instead of "Sync everything".
+    customizeSync.click();
     // Disable "Settings".
     syncControls.$.osPreferencesControl.click();
     const prefs = await browserProxy.whenCalled('setOsSyncDatatypes');
@@ -163,6 +178,7 @@
     const expectedPrefs = getSyncAllPrefs();
     expectedPrefs.syncAllOsTypes = false;
     expectedPrefs.osPreferencesSynced = false;
+    expectedPrefs.wallpaperEnabled = false;
     assertEquals(JSON.stringify(expectedPrefs), JSON.stringify(prefs));
   });
 });
diff --git a/chrome/test/data/webui/settings/privacy_page_test.ts b/chrome/test/data/webui/settings/privacy_page_test.ts
index a8bf155..4303f7d 100644
--- a/chrome/test/data/webui/settings/privacy_page_test.ts
+++ b/chrome/test/data/webui/settings/privacy_page_test.ts
@@ -149,14 +149,14 @@
     // All redesigned pages, except notifications, protocol handlers, pdf
     // documents and protected content (except chromeos and win), will use a
     // settings-category-default-radio-group.
-    // <if expr="chromeos_ash or is_win">
+    // <if expr="chromeos_ash or chromeos_lacros or is_win">
     assertEquals(
         page.shadowRoot!
             .querySelectorAll('settings-category-default-radio-group')
             .length,
         redesignedPages.length - 3);
     // </if>
-    // <if expr="not chromeos_ash and not is_win">
+    // <if expr="not chromeos_ash and not chromeos_lacros and not is_win">
     assertEquals(
         page.shadowRoot!
             .querySelectorAll('settings-category-default-radio-group')
diff --git a/chrome/test/interaction/interaction_sequence_browser_util.cc b/chrome/test/interaction/interaction_sequence_browser_util.cc
index 1059d12c..8704dcf 100644
--- a/chrome/test/interaction/interaction_sequence_browser_util.cc
+++ b/chrome/test/interaction/interaction_sequence_browser_util.cc
@@ -207,6 +207,11 @@
 }  // namespace
 
 InteractionSequenceBrowserUtil::StateChange::StateChange() = default;
+InteractionSequenceBrowserUtil::StateChange::StateChange(
+    InteractionSequenceBrowserUtil::StateChange&& other) = default;
+InteractionSequenceBrowserUtil::StateChange&
+InteractionSequenceBrowserUtil::StateChange::operator=(
+    InteractionSequenceBrowserUtil::StateChange&& other) = default;
 InteractionSequenceBrowserUtil::StateChange::~StateChange() = default;
 
 class InteractionSequenceBrowserUtil::NewTabWatcher
diff --git a/chrome/test/interaction/interaction_sequence_browser_util.h b/chrome/test/interaction/interaction_sequence_browser_util.h
index 4c35746e..5663b2b 100644
--- a/chrome/test/interaction/interaction_sequence_browser_util.h
+++ b/chrome/test/interaction/interaction_sequence_browser_util.h
@@ -66,6 +66,8 @@
   // state change *doesn't* happen in a particular length of time.
   struct StateChange {
     StateChange();
+    StateChange(StateChange&& other);
+    StateChange& operator=(StateChange&& other);
     ~StateChange();
 
     // Function to be evaluated every `polling_interval`. Must be able to
diff --git a/chrome/test/interaction/interaction_sequence_browser_util_interactive_uitest.cc b/chrome/test/interaction/interaction_sequence_browser_util_interactive_uitest.cc
index f12d504..5cc6652 100644
--- a/chrome/test/interaction/interaction_sequence_browser_util_interactive_uitest.cc
+++ b/chrome/test/interaction/interaction_sequence_browser_util_interactive_uitest.cc
@@ -286,117 +286,3 @@
 
   EXPECT_CALL_IN_SCOPE(completed, Run, sequence->RunSynchronouslyForTesting());
 }
-
-// This test checks that we can attach to a WebUI that is embedded in a tab.
-IN_PROC_BROWSER_TEST_F(InteractionSequenceBrowserUtilInteractiveUiTest,
-                       CompareScreenshot_TabWebUI) {
-  UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
-  UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
-
-  auto download_page = InteractionSequenceBrowserUtil::ForExistingTabInBrowser(
-      browser(), kPrimaryTabPageElementId);
-  auto test_util = CreateInteractionTestUtil();
-  const ui::ElementContext context = browser()->window()->GetElementContext();
-
-  auto sequence =
-      ui::InteractionSequence::Builder()
-          .SetCompletedCallback(completed.Get())
-          .SetAbortedCallback(aborted.Get())
-          .SetContext(context)
-          .AddStep(ui::InteractionSequence::StepBuilder()
-                       .SetType(ui::InteractionSequence::StepType::kShown)
-                       .SetElementID(kPrimaryTabPageElementId)
-                       .Build())
-          .AddStep(ui::InteractionSequence::StepBuilder()
-                       .SetType(ui::InteractionSequence::StepType::kShown)
-                       .SetElementID(kAppMenuButtonElementId)
-                       .SetStartCallback(base::BindLambdaForTesting(
-                           [&](ui::InteractionSequence*,
-                               ui::TrackedElement* element) {
-                             test_util->PressButton(element);
-                           }))
-                       .Build())
-          .AddStep(ui::InteractionSequence::StepBuilder()
-                       .SetType(ui::InteractionSequence::StepType::kShown)
-                       .SetElementID(AppMenuModel::kDownloadsMenuItem)
-                       .SetMustRemainVisible(false)
-                       .SetStartCallback(base::BindLambdaForTesting(
-                           [&](ui::InteractionSequence*,
-                               ui::TrackedElement* element) {
-                             test_util->SelectMenuItem(element);
-                           }))
-                       .Build())
-          .AddStep(
-              ui::InteractionSequence::StepBuilder()
-                  .SetType(ui::InteractionSequence::StepType::kShown)
-                  .SetElementID(kPrimaryTabPageElementId)
-                  .SetTransitionOnlyOnEvent(true)
-                  .SetStartCallback(base::BindLambdaForTesting(
-                      [&](ui::InteractionSequence*,
-                          ui::TrackedElement* element) {
-                        EXPECT_TRUE(
-                            InteractionSequenceBrowserUtil::CompareScreenshot(
-                                element, std::string(), "3600270"));
-                      }))
-                  .Build())
-          .Build();
-
-  EXPECT_CALL_IN_SCOPE(completed, Run, sequence->RunSynchronouslyForTesting());
-}
-
-// This test checks that we can attach to a WebUI that is not embedded in a tab.
-IN_PROC_BROWSER_TEST_F(InteractionSequenceBrowserUtilInteractiveUiTest,
-                       CompareScreenshot_SecondaryWebUI) {
-  UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
-  UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
-
-  std::unique_ptr<InteractionSequenceBrowserUtil> tab_search_page;
-  auto test_util = CreateInteractionTestUtil();
-  const ui::ElementContext context = browser()->window()->GetElementContext();
-  base::raw_ptr<WebUIBubbleDialogView> bubble_view = nullptr;
-
-  auto sequence =
-      ui::InteractionSequence::Builder()
-          .SetCompletedCallback(completed.Get())
-          .SetAbortedCallback(aborted.Get())
-          .SetContext(context)
-          .AddStep(ui::InteractionSequence::StepBuilder()
-                       .SetType(ui::InteractionSequence::StepType::kShown)
-                       .SetElementID(kTabSearchButtonElementId)
-                       .SetStartCallback(base::BindLambdaForTesting(
-                           [&](ui::InteractionSequence*,
-                               ui::TrackedElement* element) {
-                             test_util->PressButton(element);
-                           }))
-                       .Build())
-          .AddStep(
-              ui::InteractionSequence::StepBuilder()
-                  .SetType(ui::InteractionSequence::StepType::kShown)
-                  .SetElementID(kTabSearchBubbleElementId)
-                  .SetStartCallback(base::BindLambdaForTesting(
-                      [&](ui::InteractionSequence*,
-                          ui::TrackedElement* element) {
-                        bubble_view = views::AsViewClass<WebUIBubbleDialogView>(
-                            element->AsA<views::TrackedElementViews>()->view());
-                        tab_search_page =
-                            InteractionSequenceBrowserUtil::ForNonTabWebView(
-                                bubble_view->web_view(),
-                                kTabSearchPageElementId);
-                      }))
-                  .Build())
-          .AddStep(
-              ui::InteractionSequence::StepBuilder()
-                  .SetType(ui::InteractionSequence::StepType::kShown)
-                  .SetElementID(kTabSearchPageElementId)
-                  .SetStartCallback(base::BindLambdaForTesting(
-                      [&](ui::InteractionSequence* sequence,
-                          ui::TrackedElement* element) {
-                        EXPECT_TRUE(
-                            InteractionSequenceBrowserUtil::CompareScreenshot(
-                                element, std::string(), "3600270"));
-                      }))
-                  .Build())
-          .Build();
-
-  EXPECT_CALL_IN_SCOPE(completed, Run, sequence->RunSynchronouslyForTesting());
-}
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index 720d509..cba43b8 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -231,7 +231,8 @@
           ]
         }
 
-        if (!is_cast_desktop_build && !is_cast_audio_only && !enable_assistant) {
+        if (!is_cast_desktop_build && !is_cast_audio_only &&
+            !enable_assistant) {
           # TODO(mbjorge): The VideoPlaybackMp4 test is failing on v1 devices.
           # Temporarily disable it as part of an effort to re-green the unittests.
           # Re-enable once the tests have been fixed. Limitations in the filter
@@ -721,6 +722,7 @@
     deps = [
       ":cast_shell_apk_assets",
       "//base:base_java",
+      "//build/android:build_java",
       "//chromecast/android:libcast_shell_android",
       "//chromecast/browser/android:cast_shell_java",
       "//components/crash/core/app:chrome_crashpad_handler_named_as_so",
@@ -755,6 +757,7 @@
       product_config_java_packages = [ "org.chromium.chromecast.shell" ]
       deps = [
         "//base:base_java",
+        "//build/android:build_java",
         "//chromecast/browser/android:cast_browser_java",
         "//components/crash/core/app:chrome_crashpad_handler_named_as_so",
         "//components/viz/service:service_java",
diff --git a/chromecast/base/BUILD.gn b/chromecast/base/BUILD.gn
index 0bf2e10..8595c98 100644
--- a/chromecast/base/BUILD.gn
+++ b/chromecast/base/BUILD.gn
@@ -354,6 +354,7 @@
 
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
       "//third_party/androidx:androidx_core_core_java",
     ]
@@ -400,6 +401,7 @@
       ":cast_base_test_utils_java",
       "//base:base_java",
       "//base:base_junit_test_support",
+      "//build/android:build_java",
       "//third_party/hamcrest:hamcrest_java",
     ]
   }
diff --git a/chromecast/browser/android/BUILD.gn b/chromecast/browser/android/BUILD.gn
index 80436f3..c34ac44f 100644
--- a/chromecast/browser/android/BUILD.gn
+++ b/chromecast/browser/android/BUILD.gn
@@ -96,6 +96,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chromecast/base:base_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
@@ -122,6 +123,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chromecast/base:base_java",
     "//third_party/androidx:androidx_localbroadcastmanager_localbroadcastmanager_java",
   ]
@@ -136,6 +138,7 @@
   ":cast_intents_java",
   ":reactive_android_java",
   "//base:base_java",
+  "//build/android:build_java",
   "//chromecast/base:base_java",
   "//chromecast/media/cma/backend/android:audio_track_java",
   "//components/crash/android:java",
@@ -259,6 +262,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//chromecast/base:base_java",
     "//chromecast/base:cast_base_test_utils_java",
     "//content/public/android:content_java",
diff --git a/chromecast/media/cma/backend/android/BUILD.gn b/chromecast/media/cma/backend/android/BUILD.gn
index 95e982d..5d42851 100644
--- a/chromecast/media/cma/backend/android/BUILD.gn
+++ b/chromecast/media/cma/backend/android/BUILD.gn
@@ -60,6 +60,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//chromecast/base:base_java",
     "//chromecast/public:volume_control_enums_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 2eacf14..23f9a9e3 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-14743.0.0
\ No newline at end of file
+14746.0.0
diff --git a/chromeos/dbus/resourced/resourced_client.cc b/chromeos/dbus/resourced/resourced_client.cc
index f366c61..9f45b9a 100644
--- a/chromeos/dbus/resourced/resourced_client.cc
+++ b/chromeos/dbus/resourced/resourced_client.cc
@@ -8,7 +8,6 @@
 #include "base/logging.h"
 #include "base/observer_list.h"
 #include "base/process/process_metrics.h"
-#include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 6c451fb..295990c 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -696,6 +696,7 @@
       ":components_browsertests_resources",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//content/public/test/android:content_java_test_support",
       "//content/shell/android:content_shell_browsertests_java",
       "//testing/android/native_test:native_test_java",
diff --git a/components/about_ui/android/BUILD.gn b/components/about_ui/android/BUILD.gn
index 8c9ea3f..376c344b 100644
--- a/components/about_ui/android/BUILD.gn
+++ b/components/about_ui/android/BUILD.gn
@@ -9,6 +9,9 @@
 
 android_library("aboutui_java") {
   sources = [ "java/src/org/chromium/components/aboutui/CreditUtils.java" ]
-  deps = [ "//base:base_java" ]
+  deps = [
+    "//base:base_java",
+    "//build/android:build_java",
+  ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
diff --git a/components/android_autofill/browser/BUILD.gn b/components/android_autofill/browser/BUILD.gn
index 7812257..0e312fb6 100644
--- a/components/android_autofill/browser/BUILD.gn
+++ b/components/android_autofill/browser/BUILD.gn
@@ -18,6 +18,7 @@
   srcjar_deps = [ ":autofill_aidl" ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/autofill/android:autofill_java",
     "//components/autofill/core/common/mojom:mojo_types_java",
     "//components/version_info/android:version_constants_java",
diff --git a/components/android_autofill/browser/test_support/BUILD.gn b/components/android_autofill/browser/test_support/BUILD.gn
index b9cfb47f..67e63fe 100644
--- a/components/android_autofill/browser/test_support/BUILD.gn
+++ b/components/android_autofill/browser/test_support/BUILD.gn
@@ -17,6 +17,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:jni_java",
+    "//build/android:build_java",
     "//components/android_autofill/browser:autofill_aidl",
     "//components/android_autofill/browser:java",
     "//content/public/android:content_java",
diff --git a/components/autofill_assistant/android/BUILD.gn b/components/autofill_assistant/android/BUILD.gn
index 293abf2ed..10c56c0 100644
--- a/components/autofill_assistant/android/BUILD.gn
+++ b/components/autofill_assistant/android/BUILD.gn
@@ -19,6 +19,7 @@
     ":public_dependencies_java",
     ":public_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/autofill/android:autofill_java",
     "//components/autofill/android:prefeditor_autofill_java",
     "//components/browser_ui/bottomsheet/android:java",
@@ -175,6 +176,7 @@
     ":public_dependencies_java",
     "//base:base_java",
     "//base:jni_java",
+    "//build/android:build_java",
     "//components/browser_ui/bottomsheet/android:java",
     "//components/favicon/android:java",
     "//components/image_fetcher:java",
@@ -357,6 +359,7 @@
   deps = [
     ":animated_poodle_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_appcompat_appcompat_resources_java",
     "//ui/android:ui_java",
   ]
diff --git a/components/autofill_assistant/browser/starter_heuristic.cc b/components/autofill_assistant/browser/starter_heuristic.cc
index 9c1482e..fc306b82 100644
--- a/components/autofill_assistant/browser/starter_heuristic.cc
+++ b/components/autofill_assistant/browser/starter_heuristic.cc
@@ -87,11 +87,9 @@
     }
 
     std::string error;
-    const auto& url_conditions_dict =
-        base::Value::AsDictionaryValue(*url_conditions);
     condition_sets.emplace_back(
         url_matcher::URLMatcherFactory::CreateFromURLFilterDictionary(
-            url_matcher_.condition_factory(), &url_conditions_dict,
+            url_matcher_.condition_factory(), url_conditions->GetDict(),
             next_condition_set_id, &error));
     if (!error.empty()) {
       VLOG(1) << "Error pasing url conditions: " << error;
diff --git a/components/background_task_scheduler/BUILD.gn b/components/background_task_scheduler/BUILD.gn
index 4417a697..5de4c4a 100644
--- a/components/background_task_scheduler/BUILD.gn
+++ b/components/background_task_scheduler/BUILD.gn
@@ -131,6 +131,7 @@
       "//base:base_java",
       "//base:base_java_test_support",
       "//base:base_junit_test_support",
+      "//build/android:build_java",
       "//components/background_task_scheduler:public_java",
       "//third_party/android_deps:chromium_play_services_availability_shadows_java",
       "//third_party/android_deps:robolectric_all_java",
diff --git a/components/background_task_scheduler/internal/BUILD.gn b/components/background_task_scheduler/internal/BUILD.gn
index 05cf1f1a..2d3be5a 100644
--- a/components/background_task_scheduler/internal/BUILD.gn
+++ b/components/background_task_scheduler/internal/BUILD.gn
@@ -32,6 +32,7 @@
       "$google_play_services_package:google_play_services_gcm_java",
       "$google_play_services_package:google_play_services_tasks_java",
       "//base:base_java",
+      "//build/android:build_java",
       "//components/background_task_scheduler:background_task_scheduler_task_ids_java",
       "//components/background_task_scheduler:public_java",
       "//content/public/android:content_main_dex_java",
@@ -104,6 +105,7 @@
       "$google_play_services_package:google_play_services_tasks_java",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//components/background_task_scheduler:background_task_scheduler_task_ids_java",
       "//components/background_task_scheduler:public_java",
       "//content/public/test/android:content_java_test_support",
diff --git a/components/browser_ui/accessibility/android/BUILD.gn b/components/browser_ui/accessibility/android/BUILD.gn
index 23b6a63..3c68ece 100644
--- a/components/browser_ui/accessibility/android/BUILD.gn
+++ b/components/browser_ui/accessibility/android/BUILD.gn
@@ -39,6 +39,7 @@
     ":constants_java",
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/settings/android:java",
     "//content/public/android:content_full_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/browser_ui/bottomsheet/android/internal/BUILD.gn b/components/browser_ui/bottomsheet/android/internal/BUILD.gn
index 108bde4..107b78d 100644
--- a/components/browser_ui/bottomsheet/android/internal/BUILD.gn
+++ b/components/browser_ui/bottomsheet/android/internal/BUILD.gn
@@ -41,6 +41,7 @@
     ":java",
     "//base:base_java",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//third_party/android_deps:robolectric_all_java",
     "//third_party/junit",
     "//third_party/mockito:mockito_java",
@@ -58,6 +59,7 @@
     "../test:java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//components/browser_ui/widget/android:java",
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/junit",
diff --git a/components/browser_ui/bottomsheet/android/test/BUILD.gn b/components/browser_ui/bottomsheet/android/test/BUILD.gn
index 2ccb711..eec9cc5d 100644
--- a/components/browser_ui/bottomsheet/android/test/BUILD.gn
+++ b/components/browser_ui/bottomsheet/android/test/BUILD.gn
@@ -18,6 +18,7 @@
     "../internal:java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
diff --git a/components/browser_ui/client_certificate/android/BUILD.gn b/components/browser_ui/client_certificate/android/BUILD.gn
index 7890738b..d113797 100644
--- a/components/browser_ui/client_certificate/android/BUILD.gn
+++ b/components/browser_ui/client_certificate/android/BUILD.gn
@@ -20,6 +20,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/widget/android:java_resources",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/browser_ui/contacts_picker/android/BUILD.gn b/components/browser_ui/contacts_picker/android/BUILD.gn
index 8149a6a..57cf0d1d 100644
--- a/components/browser_ui/contacts_picker/android/BUILD.gn
+++ b/components/browser_ui/contacts_picker/android/BUILD.gn
@@ -36,6 +36,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/util/android:java",
     "//components/browser_ui/widget/android:java",
     "//components/payments/mojom:mojom_java",
diff --git a/components/browser_ui/media/android/BUILD.gn b/components/browser_ui/media/android/BUILD.gn
index 679af824..7719302 100644
--- a/components/browser_ui/media/android/BUILD.gn
+++ b/components/browser_ui/media/android/BUILD.gn
@@ -89,6 +89,7 @@
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//services/media_session/public/cpp/android:media_session_java",
     "//services/media_session/public/mojom:mojom_java",
diff --git a/components/browser_ui/photo_picker/android/BUILD.gn b/components/browser_ui/photo_picker/android/BUILD.gn
index fe49841..adbdd30 100644
--- a/components/browser_ui/photo_picker/android/BUILD.gn
+++ b/components/browser_ui/photo_picker/android/BUILD.gn
@@ -42,6 +42,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/util/android:java",
     "//components/browser_ui/widget/android:java",
     "//content/public/android:content_java",
@@ -142,6 +143,7 @@
     ":java_resources",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/test/android:chrome_java_test_support",
     "//components/browser_ui/test/android:test_support_java",
     "//components/browser_ui/widget/android:java",
diff --git a/components/browser_ui/share/android/BUILD.gn b/components/browser_ui/share/android/BUILD.gn
index 7ee3147..21132c12 100644
--- a/components/browser_ui/share/android/BUILD.gn
+++ b/components/browser_ui/share/android/BUILD.gn
@@ -72,6 +72,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/android:chrome_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/browser_ui/util/android/BUILD.gn b/components/browser_ui/util/android/BUILD.gn
index 64e3603..971e6c9 100644
--- a/components/browser_ui/util/android/BUILD.gn
+++ b/components/browser_ui/util/android/BUILD.gn
@@ -22,6 +22,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//cc:cc_java",
     "//components/embedder_support/android:util_java",
     "//components/url_formatter/android:url_formatter_java",
diff --git a/components/browser_ui/webshare/android/BUILD.gn b/components/browser_ui/webshare/android/BUILD.gn
index 24424f0..cc96c6e 100644
--- a/components/browser_ui/webshare/android/BUILD.gn
+++ b/components/browser_ui/webshare/android/BUILD.gn
@@ -38,6 +38,7 @@
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//third_party/android_deps:robolectric_all_java",
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/blink/public/mojom:android_mojo_bindings_java",
diff --git a/components/browser_ui/widget/android/BUILD.gn b/components/browser_ui/widget/android/BUILD.gn
index a0e8693..49d9c7e 100644
--- a/components/browser_ui/widget/android/BUILD.gn
+++ b/components/browser_ui/widget/android/BUILD.gn
@@ -331,6 +331,7 @@
     ":test_support_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//components/browser_ui/test/android:test_support_java",
     "//components/browser_ui/theme/android:java_resources",
     "//content/public/test/android:content_java_test_support",
@@ -394,6 +395,7 @@
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//third_party/android_deps:robolectric_all_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_test_runner_java",
diff --git a/components/commerce/core/android/BUILD.gn b/components/commerce/core/android/BUILD.gn
index cb4da26..3eaf399 100644
--- a/components/commerce/core/android/BUILD.gn
+++ b/components/commerce/core/android/BUILD.gn
@@ -12,5 +12,6 @@
   deps = [
     "//base:base_java",
     "//base:jni_java",
+    "//build/android:build_java",
   ]
 }
diff --git a/components/component_updater/android/BUILD.gn b/components/component_updater/android/BUILD.gn
index ad474ed..bf663322 100644
--- a/components/component_updater/android/BUILD.gn
+++ b/components/component_updater/android/BUILD.gn
@@ -13,6 +13,7 @@
   deps = [
     ":background_task_update_scheduler_jni_headers",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/background_task_scheduler:background_task_scheduler_java",
     "//components/background_task_scheduler:background_task_scheduler_task_ids_java",
     "//third_party/android_deps:chromium_play_services_availability_java",
@@ -56,6 +57,7 @@
     ":component_provider_service_aidl_java",
     ":embedded_component_loader_jni_headers",
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_main_dex_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
diff --git a/components/content_capture/android/BUILD.gn b/components/content_capture/android/BUILD.gn
index a2f9cd2..0488413 100644
--- a/components/content_capture/android/BUILD.gn
+++ b/components/content_capture/android/BUILD.gn
@@ -20,6 +20,7 @@
 android_library("java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
diff --git a/components/content_capture/android/test_support/BUILD.gn b/components/content_capture/android/test_support/BUILD.gn
index 1e6eec4f..683f8bc 100644
--- a/components/content_capture/android/test_support/BUILD.gn
+++ b/components/content_capture/android/test_support/BUILD.gn
@@ -18,6 +18,7 @@
 android_library("java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
diff --git a/components/content_creation/notes/android/BUILD.gn b/components/content_creation/notes/android/BUILD.gn
index 1d02a2a..247f8a7b9 100644
--- a/components/content_creation/notes/android/BUILD.gn
+++ b/components/content_creation/notes/android/BUILD.gn
@@ -25,6 +25,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_core_core_java",
   ]
diff --git a/components/content_creation/reactions/android/BUILD.gn b/components/content_creation/reactions/android/BUILD.gn
index 97ae80c..4a8f6bf 100644
--- a/components/content_creation/reactions/android/BUILD.gn
+++ b/components/content_creation/reactions/android/BUILD.gn
@@ -16,6 +16,7 @@
   deps = [
     ":reaction_types_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_core_core_java",
   ]
diff --git a/components/content_settings/android/BUILD.gn b/components/content_settings/android/BUILD.gn
index ae44ce4..3687f65f 100644
--- a/components/content_settings/android/BUILD.gn
+++ b/components/content_settings/android/BUILD.gn
@@ -20,6 +20,7 @@
   deps = [
     ":content_settings_enums_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
diff --git a/components/content_settings/core/browser/content_settings_default_provider.cc b/components/content_settings/core/browser/content_settings_default_provider.cc
index 1f6642ba..3a0c37be 100644
--- a/components/content_settings/core/browser/content_settings_default_provider.cc
+++ b/components/content_settings/core/browser/content_settings_default_provider.cc
@@ -55,10 +55,10 @@
 #endif  // !BUILDFLAG(IS_ANDROID)
 #endif  // !BUILDFLAG(IS_IOS)
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
 // This setting was moved and should be migrated on profile startup.
 const char kDeprecatedEnableDRM[] = "settings.privacy.drm_enabled";
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
 
 ContentSetting GetDefaultValue(const WebsiteSettingsInfo* info) {
   const base::Value& initial_default = info->initial_default_value();
@@ -138,9 +138,9 @@
 #endif  // !BUILDFLAG(IS_ANDROID)
 #endif  // !BUILDFLAG(IS_IOS)
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
   registry->RegisterBooleanPref(kDeprecatedEnableDRM, true);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
 }
 
 DefaultProvider::DefaultProvider(PrefService* prefs, bool off_the_record)
@@ -423,7 +423,7 @@
 #endif  // !BUILDFLAG(IS_ANDROID)
 #endif  // !BUILDFLAG(IS_IOS)
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
   // TODO(crbug.com/1191642): Remove this migration logic in M100.
   WebsiteSettingsRegistry* website_settings =
       WebsiteSettingsRegistry::GetInstance();
@@ -437,7 +437,7 @@
                                                : CONTENT_SETTING_BLOCK);
   }
   prefs_->ClearPref(kDeprecatedEnableDRM);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
 }
 
 }  // namespace content_settings
diff --git a/components/content_settings/core/browser/content_settings_registry_unittest.cc b/components/content_settings/core/browser/content_settings_registry_unittest.cc
index a816caa..b7cd0f5a 100644
--- a/components/content_settings/core/browser/content_settings_registry_unittest.cc
+++ b/components/content_settings/core/browser/content_settings_registry_unittest.cc
@@ -166,7 +166,7 @@
   EXPECT_FALSE(info->IsDefaultSettingValid(CONTENT_SETTING_ALLOW));
 #endif
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
   info = registry()->Get(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER);
   EXPECT_TRUE(info->IsDefaultSettingValid(CONTENT_SETTING_ALLOW));
 #endif
diff --git a/components/crash/android/BUILD.gn b/components/crash/android/BUILD.gn
index 3a3788b..8b469f5a 100644
--- a/components/crash/android/BUILD.gn
+++ b/components/crash/android/BUILD.gn
@@ -23,6 +23,7 @@
 android_library("java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/minidump_uploader:minidump_uploader_java",
     "//components/version_info/android:version_constants_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
@@ -102,7 +103,10 @@
 }
 
 android_library("handler_java") {
-  deps = [ "//base:base_java" ]
+  deps = [
+    "//base:base_java",
+    "//build/android:build_java",
+  ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   sources = _java_handler_jni_sources
 }
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn
index 5a0dfe94d..a220879 100644
--- a/components/cronet/android/BUILD.gn
+++ b/components/cronet/android/BUILD.gn
@@ -897,6 +897,7 @@
       ":cronet_impl_all_java",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//net/android:net_java_test_support",
       "//third_party/android_sdk:android_test_base_java",
       "//third_party/junit",
@@ -929,6 +930,7 @@
       ":cronet_api_java",
       ":cronet_impl_all_java",
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/android_sdk:android_test_base_java",
       "//third_party/android_support_test_runner:runner_java",
       "//third_party/junit",
@@ -1068,6 +1070,7 @@
       ":cronet_test_apk_resources",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//net/android:net_java",
       "//net/android:net_java_test_support",
       "//third_party/android_sdk:android_test_base_java",
@@ -1154,6 +1157,7 @@
       ":cronet_test_apk_resources",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//third_party/android_sdk:android_test_base_java",
       "//third_party/android_sdk:android_test_mock_java",
       "//third_party/android_support_test_runner:runner_java",
@@ -1194,6 +1198,7 @@
       ":cronet_javatests",
       ":cronet_test_apk_java",
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/android_sdk:android_test_mock_java",
       "//third_party/junit",
     ]
@@ -1297,6 +1302,7 @@
   jar_src("jar_cronet_impl_native_java_source") {
     src_search_dirs = [
       "//base/android/java/src",
+      "//build/android/java/src",
       "//components/cronet/android/java/src",
       "//net/android/java/src",
       "//url/android/java/src",
@@ -1304,6 +1310,7 @@
     source_deps = [
       ":cronet_impl_native_base_java",
       "//base:base_java",
+      "//build/android:build_java",
       "//net/android:net_java",
       "//url:url_java",
     ]
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc
index a5688c7f..2c58135 100644
--- a/components/cronet/url_request_context_config.cc
+++ b/components/cronet/url_request_context_config.cc
@@ -5,6 +5,7 @@
 #include "components/cronet/url_request_context_config.h"
 
 #include <memory>
+#include <type_traits>
 #include <utility>
 
 #include "base/json/json_reader.h"
@@ -234,8 +235,8 @@
 template <typename T, typename F>
 auto map(absl::optional<T> maybe, F&& f) {
   if (!maybe)
-    return absl::optional<base::invoke_result_t<F, T>>();
-  return absl::optional<base::invoke_result_t<F, T>>(f(maybe.value()));
+    return absl::optional<std::invoke_result_t<F, T>>();
+  return absl::optional<std::invoke_result_t<F, T>>(f(maybe.value()));
 }
 
 }  // namespace
diff --git a/components/dom_distiller/content/browser/android/BUILD.gn b/components/dom_distiller/content/browser/android/BUILD.gn
index 2b2ef46..9b8fd399 100644
--- a/components/dom_distiller/content/browser/android/BUILD.gn
+++ b/components/dom_distiller/content/browser/android/BUILD.gn
@@ -7,6 +7,7 @@
 android_library("dom_distiller_content_java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/dom_distiller/core/android:dom_distiller_core_java",
     "//content/public/android:content_java",
   ]
diff --git a/components/dom_distiller/core/android/BUILD.gn b/components/dom_distiller/core/android/BUILD.gn
index 95532b88..ca28765 100644
--- a/components/dom_distiller/core/android/BUILD.gn
+++ b/components/dom_distiller/core/android/BUILD.gn
@@ -7,6 +7,7 @@
 android_library("dom_distiller_core_java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/dom_distiller/core/mojom:mojom_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//url:gurl_java",
diff --git a/components/download/internal/common/BUILD.gn b/components/download/internal/common/BUILD.gn
index 1ddc494..29b38976 100644
--- a/components/download/internal/common/BUILD.gn
+++ b/components/download/internal/common/BUILD.gn
@@ -117,6 +117,7 @@
 
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/android_provider:android_provider_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
     ]
diff --git a/components/download/network/BUILD.gn b/components/download/network/BUILD.gn
index a57934e5..9d4a594 100644
--- a/components/download/network/BUILD.gn
+++ b/components/download/network/BUILD.gn
@@ -53,6 +53,7 @@
 
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//net/android:net_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
     ]
diff --git a/components/embedder_support/android/BUILD.gn b/components/embedder_support/android/BUILD.gn
index 5ac1ca6..9f2354a5 100644
--- a/components/embedder_support/android/BUILD.gn
+++ b/components/embedder_support/android/BUILD.gn
@@ -41,7 +41,10 @@
 }
 
 android_library("application_java") {
-  deps = [ "//base:base_java" ]
+  deps = [
+    "//base:base_java",
+    "//build/android:build_java",
+  ]
   sources = [
     "java/src/org/chromium/components/embedder_support/application/ClassLoaderContextWrapperFactory.java",
     "java/src/org/chromium/components/embedder_support/application/FirebaseConfig.java",
@@ -60,6 +63,7 @@
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/url_formatter/android:url_formatter_java",
     "//content/public/android:content_main_dex_java",
     "//net/android:net_java",
@@ -142,6 +146,7 @@
 android_library("view_java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//ui/android:ui_no_recycler_view_java",
   ]
@@ -203,6 +208,7 @@
   deps = [
     ":web_contents_delegate_java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_core_core_java",
@@ -268,6 +274,7 @@
   deps = [
     ":util_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/junit",
   ]
   sources = [ "native_java_unittests/src/org/chromium/components/embedder_support/util/InputStreamUnittest.java" ]
@@ -322,6 +329,7 @@
     ":web_contents_delegate_java_resources",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
diff --git a/components/external_intents/android/BUILD.gn b/components/external_intents/android/BUILD.gn
index c5a8bd0..cabb0f5c2 100644
--- a/components/external_intents/android/BUILD.gn
+++ b/components/external_intents/android/BUILD.gn
@@ -20,6 +20,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/embedder_support/android:util_java",
     "//components/navigation_interception/android:navigation_interception_java",
     "//components/url_formatter/android:url_formatter_java",
diff --git a/components/externalauth/android/BUILD.gn b/components/externalauth/android/BUILD.gn
index b1239f692..fa752e2 100644
--- a/components/externalauth/android/BUILD.gn
+++ b/components/externalauth/android/BUILD.gn
@@ -53,6 +53,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//third_party/android_deps:robolectric_all_java",
     "//third_party/junit",
     "//third_party/mockito:mockito_java",
diff --git a/components/favicon/android/BUILD.gn b/components/favicon/android/BUILD.gn
index a0d2d845..485a2ec 100644
--- a/components/favicon/android/BUILD.gn
+++ b/components/favicon/android/BUILD.gn
@@ -9,6 +9,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/util/android:java",
     "//content/public/android:content_full_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/feature_engagement/internal/BUILD.gn b/components/feature_engagement/internal/BUILD.gn
index 1aedb72..4a2f99d 100644
--- a/components/feature_engagement/internal/BUILD.gn
+++ b/components/feature_engagement/internal/BUILD.gn
@@ -133,6 +133,7 @@
 
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//components/feature_engagement/public:public_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
       "//ui/android:ui_java",
diff --git a/components/feed/core/v2/testdata/request.textproto b/components/feed/core/v2/testdata/request.textproto
index 8a98e0d..e7b366a8 100644
--- a/components/feed/core/v2/testdata/request.textproto
+++ b/components/feed/core/v2/testdata/request.textproto
@@ -3,32 +3,53 @@
   client_info {
     platform_type: ANDROID_ID
     platform_version {
-      major: 10
-      architecture: ARM64
-      build_type: DEV
-      api_version: 29
+      major: 9
+      minor: 0
+      revision: 0
+      architecture: X86
+      build_type: RELEASE
+      api_version: 28
     }
     app_type: CHROME_ANDROID
     app_version {
-      major: 79
+      major: 103
       minor: 0
-      build: 3945
-      revision: 93
-      architecture: ARM64
-      build_type: RELEASE
+      build: 5018
+      revision: 0
+      architecture: X86
+      build_type: UNKNOWN_BUILD_TYPE
+      api_version: 28
     }
     locale: "en-US"
     display_info {
-      screen_density: 2.625
-      screen_width_in_pixels: 1080
-      screen_height_in_pixels: 1794
+      screen_density: 1.5
+      screen_width_in_pixels: 480
+      screen_height_in_pixels: 800
+    }
+    chrome_client_info {
     }
   }
   feed_query {
-    reason: SCHEDULED_REFRESH
+    reason: MANUAL_REFRESH
+    feed_entry_point_data {
+      feed_entry_point_source_value: 19
+    }
   }
-  client_capability: BASE_UI
+  client_capability: CARD_MENU
+  client_capability: LOTTIE_ANIMATIONS
+  client_capability: LONG_PRESS_CARD_MENU
+  client_capability: SHARE
+  client_capability: OPEN_IN_TAB
+  client_capability: OPEN_IN_INCOGNITO
+  client_capability: DISMISS_COMMAND
+  client_capability: INFINITE_FEED
+  client_capability: PREFETCH_METADATA
   client_capability: REQUEST_SCHEDULE
-  consistency_token {
-  }
+  client_capability: UI_THEME_V2
+  client_capability: UNDO_FOR_DISMISS_COMMAND
+  client_capability: MATERIAL_NEXT_BASELINE
+  client_capability: CONTENT_LIFETIME
+  client_capability: READ_LATER
+  client_capability: ON_DEVICE_USER_PROFILE
 }
+
diff --git a/components/find_in_page/android/BUILD.gn b/components/find_in_page/android/BUILD.gn
index 1f83721..ddebfd4 100644
--- a/components/find_in_page/android/BUILD.gn
+++ b/components/find_in_page/android/BUILD.gn
@@ -18,6 +18,7 @@
     ":java_resources",
     ":jni_headers",
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//ui/android:ui_java",
   ]
diff --git a/components/gcm_driver/android/BUILD.gn b/components/gcm_driver/android/BUILD.gn
index f7de29aa..ada6ea62 100644
--- a/components/gcm_driver/android/BUILD.gn
+++ b/components/gcm_driver/android/BUILD.gn
@@ -11,6 +11,7 @@
 android_library("gcm_driver_java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/android_deps:com_google_code_findbugs_jsr305_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
diff --git a/components/gcm_driver/instance_id/android/BUILD.gn b/components/gcm_driver/instance_id/android/BUILD.gn
index 0e0beb64..117bb2a0 100644
--- a/components/gcm_driver/instance_id/android/BUILD.gn
+++ b/components/gcm_driver/instance_id/android/BUILD.gn
@@ -17,6 +17,7 @@
   deps = [
     "$google_play_services_package:google_play_services_iid_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/gcm_driver/android:gcm_driver_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
diff --git a/components/heap_profiling/multi_process/BUILD.gn b/components/heap_profiling/multi_process/BUILD.gn
index 2f43f5d..a29e806 100644
--- a/components/heap_profiling/multi_process/BUILD.gn
+++ b/components/heap_profiling/multi_process/BUILD.gn
@@ -34,7 +34,10 @@
   android_library("heap_profiling_java_test_support") {
     testonly = true
     sources = [ "javatests/src/org/chromium/components/heap_profiling/multi_process/HeapProfilingTestShim.java" ]
-    deps = [ "//base:base_java" ]
+    deps = [
+      "//base:base_java",
+      "//build/android:build_java",
+    ]
   }
 }
 
diff --git a/components/image_fetcher/BUILD.gn b/components/image_fetcher/BUILD.gn
index a2927f5..7355fac5 100644
--- a/components/image_fetcher/BUILD.gn
+++ b/components/image_fetcher/BUILD.gn
@@ -15,6 +15,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/util/android:java",
     "//components/embedder_support/android:simple_factory_key_java",
     "//content/public/android:content_main_dex_java",
diff --git a/components/infobars/android/BUILD.gn b/components/infobars/android/BUILD.gn
index ce350d7..52249d75 100644
--- a/components/infobars/android/BUILD.gn
+++ b/components/infobars/android/BUILD.gn
@@ -70,6 +70,7 @@
     ":infobar_android_enums_java",
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/styles/android:java",
     "//components/browser_ui/widget/android:java",
     "//components/infobars/core:infobar_enums_java",
diff --git a/components/installedapp/android/BUILD.gn b/components/installedapp/android/BUILD.gn
index 66b9f36..2f79d38 100644
--- a/components/installedapp/android/BUILD.gn
+++ b/components/installedapp/android/BUILD.gn
@@ -25,6 +25,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/webapk/android/libs/client:java",
     "//content/public/android:content_java",
     "//mojo/public/java:system_java",
@@ -73,6 +74,7 @@
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//content/public/android:content_full_java",
     "//third_party/junit",
   ]
diff --git a/components/javascript_dialogs/android/BUILD.gn b/components/javascript_dialogs/android/BUILD.gn
index a1baa9e..48c67f3 100644
--- a/components/javascript_dialogs/android/BUILD.gn
+++ b/components/javascript_dialogs/android/BUILD.gn
@@ -21,6 +21,7 @@
     ":java_resources",
     ":jni_headers",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/styles/android:java",
     "//components/browser_ui/widget/android:java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/language/android/BUILD.gn b/components/language/android/BUILD.gn
index 1703bd3..a40b786 100644
--- a/components/language/android/BUILD.gn
+++ b/components/language/android/BUILD.gn
@@ -35,6 +35,7 @@
   deps = [
     ":ulp_delegate_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
 
@@ -59,6 +60,7 @@
   deps = [
     ":ulp_delegate_java",
     "//base:base_java",
+    "//build/android:build_java",
   ]
 }
 
@@ -73,6 +75,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//components/browser_ui/widget/android:java",
     "//content/public/android:content_java",
     "//content/public/test/android:content_java_test_support",
@@ -92,6 +95,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//chrome/browser/flags:java",
     "//chrome/test/android:chrome_java_test_support",
     "//content/public/test/android:content_java_test_support",
diff --git a/components/location/android/BUILD.gn b/components/location/android/BUILD.gn
index faf8947..99938cb 100644
--- a/components/location/android/BUILD.gn
+++ b/components/location/android/BUILD.gn
@@ -25,6 +25,7 @@
   deps = [
     ":location_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//ui/android:ui_no_recycler_view_java",
   ]
   sources =
diff --git a/components/media_router/browser/android/BUILD.gn b/components/media_router/browser/android/BUILD.gn
index 31f7cda..d855224 100644
--- a/components/media_router/browser/android/BUILD.gn
+++ b/components/media_router/browser/android/BUILD.gn
@@ -16,6 +16,7 @@
     "$google_play_services_package:google_play_services_cast_framework_java",
     "$google_play_services_package:google_play_services_cast_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/media/android:java",
     "//content/public/android:content_java",
     "//services/media_session/public/cpp/android:media_session_java",
@@ -147,6 +148,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//third_party/android_deps:robolectric_all_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/media_router/test/android/cast_emulator/BUILD.gn b/components/media_router/test/android/cast_emulator/BUILD.gn
index 62f60b3e..f4421e16 100644
--- a/components/media_router/test/android/cast_emulator/BUILD.gn
+++ b/components/media_router/test/android/cast_emulator/BUILD.gn
@@ -22,6 +22,7 @@
   deps = [
     "$google_play_services_package:google_play_services_cast_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_mediarouter_mediarouter_java",
   ]
 }
diff --git a/components/messages/android/BUILD.gn b/components/messages/android/BUILD.gn
index 1f7cbde..6f781012 100644
--- a/components/messages/android/BUILD.gn
+++ b/components/messages/android/BUILD.gn
@@ -22,6 +22,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/banners/android:java",
     "//components/browser_ui/widget/android:java",
     "//content/public/android:content_java",
diff --git a/components/messages/android/internal/BUILD.gn b/components/messages/android/internal/BUILD.gn
index 0c54e71..9c66d98 100644
--- a/components/messages/android/internal/BUILD.gn
+++ b/components/messages/android/internal/BUILD.gn
@@ -30,6 +30,7 @@
     "..:java_resources",
     "..:manager_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/widget/android:java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
@@ -82,6 +83,7 @@
     "..:java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//components/browser_ui/test/android:test_support_java",
     "//components/browser_ui/widget/android:java",
     "//content/public/test/android:content_java_test_support",
diff --git a/components/messages/android/test/BUILD.gn b/components/messages/android/test/BUILD.gn
index e6ce55f..a0ca138 100644
--- a/components/messages/android/test/BUILD.gn
+++ b/components/messages/android/test/BUILD.gn
@@ -16,6 +16,7 @@
   deps = [
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//components/messages/android:java",
     "//components/messages/android/internal:java",
     "//ui/android:ui_no_recycler_view_java",
diff --git a/components/minidump_uploader/BUILD.gn b/components/minidump_uploader/BUILD.gn
index bf257d3d..26253f4 100644
--- a/components/minidump_uploader/BUILD.gn
+++ b/components/minidump_uploader/BUILD.gn
@@ -31,6 +31,7 @@
 android_library("minidump_uploader_java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/crash/android:anr_collector_java",
     "//net/android:net_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
@@ -80,6 +81,7 @@
     ":minidump_uploader_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/junit",
diff --git a/components/module_installer/android/BUILD.gn b/components/module_installer/android/BUILD.gn
index 39b6d307..032b035d 100644
--- a/components/module_installer/android/BUILD.gn
+++ b/components/module_installer/android/BUILD.gn
@@ -33,6 +33,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/crash/android:java",
     "//third_party/android_deps:com_google_android_play_core_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/module_installer/android/module_desc_java.gni b/components/module_installer/android/module_desc_java.gni
index edf39d9..9dbcbbe 100644
--- a/components/module_installer/android/module_desc_java.gni
+++ b/components/module_installer/android/module_desc_java.gni
@@ -72,6 +72,7 @@
   android_library(_target_name) {
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//components/module_installer/android:module_installer_java",
     ]
     srcjar_deps = [ ":${_target_name}__srcjar" ]
diff --git a/components/offline_items_collection/core/BUILD.gn b/components/offline_items_collection/core/BUILD.gn
index cded3c4..0f8ad3af 100644
--- a/components/offline_items_collection/core/BUILD.gn
+++ b/components/offline_items_collection/core/BUILD.gn
@@ -114,6 +114,7 @@
 
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
       "//url:gurl_java",
     ]
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn
index 77ca28f..618ffed8 100644
--- a/components/omnibox/browser/BUILD.gn
+++ b/components/omnibox/browser/BUILD.gn
@@ -424,6 +424,7 @@
     deps = [
       ":java_resources",
       "//base:base_java",
+      "//build/android:build_java",
       "//components/browser_ui/widget/android:java",
       "//components/embedder_support/android:util_java",
       "//components/query_tiles:query_tile_java",
diff --git a/components/omnibox/browser/history_fuzzy_provider.cc b/components/omnibox/browser/history_fuzzy_provider.cc
index b3af48b..7d8a23f 100644
--- a/components/omnibox/browser/history_fuzzy_provider.cc
+++ b/components/omnibox/browser/history_fuzzy_provider.cc
@@ -358,6 +358,7 @@
 
 HistoryFuzzyProvider::HistoryFuzzyProvider(AutocompleteProviderClient* client)
     : HistoryProvider(AutocompleteProvider::TYPE_HISTORY_FUZZY, client) {
+  history_service_observation_.Observe(client->GetHistoryService());
   client->GetHistoryService()->ScheduleDBTask(
       FROM_HERE,
       std::make_unique<fuzzy::LoadSignificantUrls>(
@@ -487,3 +488,13 @@
 void HistoryFuzzyProvider::OnUrlsLoaded(fuzzy::Node node) {
   root_ = std::move(node);
 }
+
+void HistoryFuzzyProvider::OnURLVisited(
+    history::HistoryService* history_service,
+    ui::PageTransition transition,
+    const history::URLRow& row,
+    const history::RedirectList& redirects,
+    base::Time visit_time) {
+  DVLOG(1) << "URL Visit: " << row.url();
+  root_.Insert(base::ASCIIToUTF16(row.url().host()), 0);
+}
diff --git a/components/omnibox/browser/history_fuzzy_provider.h b/components/omnibox/browser/history_fuzzy_provider.h
index 9462dcb..692f840 100644
--- a/components/omnibox/browser/history_fuzzy_provider.h
+++ b/components/omnibox/browser/history_fuzzy_provider.h
@@ -10,8 +10,11 @@
 #include <vector>
 
 #include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/cancelable_task_tracker.h"
+#include "components/history/core/browser/history_service.h"
+#include "components/history/core/browser/history_service_observer.h"
 #include "components/history/core/browser/history_types.h"
 #include "components/omnibox/browser/autocomplete_input.h"
 #include "components/omnibox/browser/autocomplete_match.h"
@@ -159,12 +162,14 @@
 // but efficiency is a top concern so node size is minimized, just enough to
 // get inputs back on track, not to replicate the full completion and scoring
 // of other autocomplete providers.
-class HistoryFuzzyProvider : public HistoryProvider {
+class HistoryFuzzyProvider : public HistoryProvider,
+                             public history::HistoryServiceObserver {
  public:
   explicit HistoryFuzzyProvider(AutocompleteProviderClient* client);
   HistoryFuzzyProvider(const HistoryFuzzyProvider&) = delete;
   HistoryFuzzyProvider& operator=(const HistoryFuzzyProvider&) = delete;
 
+  // HistoryProvider:
   // AutocompleteProvider. `minimal_changes` is ignored since there is no async
   // completion performed.
   void Start(const AutocompleteInput& input, bool minimal_changes) override;
@@ -185,6 +190,14 @@
   // Main thread callback to receive trie of URLs loaded from database.
   void OnUrlsLoaded(fuzzy::Node node);
 
+  // history::HistoryServiceObserver:
+  // Adds visited URL host to trie.
+  void OnURLVisited(history::HistoryService* history_service,
+                    ui::PageTransition transition,
+                    const history::URLRow& row,
+                    const history::RedirectList& redirects,
+                    base::Time visit_time) override;
+
   AutocompleteInput autocomplete_input_;
 
   // TODO(orinj): For now this is memory resident for proof of concept, but
@@ -206,6 +219,11 @@
   // Task tracker for URL data loading.
   base::CancelableTaskTracker task_tracker_;
 
+  // Tracks the observed history service, for cleanup.
+  base::ScopedObservation<history::HistoryService,
+                          history::HistoryServiceObserver>
+      history_service_observation_{this};
+
   // Weak pointer factory for callback binding safety.
   base::WeakPtrFactory<HistoryFuzzyProvider> weak_ptr_factory_{this};
 };
diff --git a/components/page_info/android/BUILD.gn b/components/page_info/android/BUILD.gn
index 31fe42d2c..87f2bab 100644
--- a/components/page_info/android/BUILD.gn
+++ b/components/page_info/android/BUILD.gn
@@ -92,6 +92,7 @@
     ":java_resources",
     ":page_info_action_enum_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/settings/android:java",
     "//components/browser_ui/site_settings/android:java",
     "//components/browser_ui/styles/android:java",
diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc
index 299a89f..d6d9c4a 100644
--- a/components/page_info/page_info.cc
+++ b/components/page_info/page_info.cc
@@ -100,7 +100,7 @@
     ContentSettingsType::BACKGROUND_SYNC,
     ContentSettingsType::SOUND,
     ContentSettingsType::AUTOMATIC_DOWNLOADS,
-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
     ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
 #endif
     ContentSettingsType::MIDI_SYSEX,
diff --git a/components/page_info/page_info_ui.cc b/components/page_info/page_info_ui.cc
index f48979d..dc198733 100644
--- a/components/page_info/page_info_ui.cc
+++ b/components/page_info/page_info_ui.cc
@@ -153,7 +153,7 @@
     {ContentSettingsType::BACKGROUND_SYNC,
      IDS_SITE_SETTINGS_TYPE_BACKGROUND_SYNC,
      IDS_SITE_SETTINGS_TYPE_BACKGROUND_SYNC_MID_SENTENCE},
-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
     {ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
      IDS_SITE_SETTINGS_TYPE_PROTECTED_MEDIA_ID,
      IDS_SITE_SETTINGS_TYPE_PROTECTED_MEDIA_ID_MID_SENTENCE},
diff --git a/components/paint_preview/player/android/BUILD.gn b/components/paint_preview/player/android/BUILD.gn
index ee9c7ca..1960a97 100644
--- a/components/paint_preview/player/android/BUILD.gn
+++ b/components/paint_preview/player/android/BUILD.gn
@@ -90,6 +90,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/styles/android:java",
     "//components/paint_preview/browser/android:java",
     "//content/public/android:content_java",
@@ -115,6 +116,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//components/paint_preview/browser/android:java",
     "//components/signin/public/android:java",
     "//components/signin/public/android:signin_java_test_support",
@@ -136,6 +138,7 @@
     ":player_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_support_test_runner:rules_java",
@@ -189,6 +192,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//ui/android:ui_full_java",
     "//url:gurl_java",
diff --git a/components/payments/content/android/BUILD.gn b/components/payments/content/android/BUILD.gn
index fcd5e1b..53603b22 100644
--- a/components/payments/content/android/BUILD.gn
+++ b/components/payments/content/android/BUILD.gn
@@ -139,6 +139,7 @@
       [ "java/src/org/chromium/components/payments/PaymentFeatureList.java" ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
 }
@@ -194,6 +195,7 @@
     ":minimal_java",
     ":service_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/autofill/android:autofill_java",
     "//components/browser_ui/bottomsheet/android:java",
     "//components/browser_ui/widget/android:java_resources",
@@ -239,6 +241,7 @@
   deps = [
     ":service_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/autofill/android:payments_autofill_java",
     "//components/payments/mojom:mojom_java",
     "//content/public/android:content_java",
@@ -343,6 +346,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//components/browser_ui/bottomsheet/android:java",
     "//components/payments/content/android:service_java",
     "//components/payments/mojom:mojom_java",
diff --git a/components/permissions/android/BUILD.gn b/components/permissions/android/BUILD.gn
index f82ec33..4cbb25e 100644
--- a/components/permissions/android/BUILD.gn
+++ b/components/permissions/android/BUILD.gn
@@ -119,6 +119,7 @@
     ":core_java",
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/modaldialog/android:java",
     "//components/content_settings/android:content_settings_enums_java",
     "//components/location/android:location_java",
@@ -142,6 +143,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/content_settings/android:content_settings_enums_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//ui/android:ui_no_recycler_view_java",
diff --git a/components/permissions/permission_util.cc b/components/permissions/permission_util.cc
index f0446a50..960bda4 100644
--- a/components/permissions/permission_util.cc
+++ b/components/permissions/permission_util.cc
@@ -190,7 +190,7 @@
     case ContentSettingsType::MEDIASTREAM_CAMERA:
     case ContentSettingsType::MEDIASTREAM_MIC:
     case ContentSettingsType::BACKGROUND_SYNC:
-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
     case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER:
 #endif
     case ContentSettingsType::SENSORS:
diff --git a/components/policy/android/BUILD.gn b/components/policy/android/BUILD.gn
index da1e407c..5dbe232 100644
--- a/components/policy/android/BUILD.gn
+++ b/components/policy/android/BUILD.gn
@@ -22,6 +22,7 @@
 android_library("policy_java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
   srcjar_deps = [ ":java_switches_srcjar" ]
@@ -75,6 +76,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//third_party/android_deps:robolectric_all_java",
     "//third_party/androidx:androidx_test_core_java",
     "//third_party/hamcrest:hamcrest_java",
@@ -94,6 +96,7 @@
   deps = [
     ":policy_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/junit",
     "//third_party/mockito:mockito_java",
   ]
diff --git a/components/policy/core/common/policy_statistics_collector.cc b/components/policy/core/common/policy_statistics_collector.cc
index c322e0dd..d3ade04 100644
--- a/components/policy/core/common/policy_statistics_collector.cc
+++ b/components/policy/core/common/policy_statistics_collector.cc
@@ -13,6 +13,9 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/notreached.h"
 #include "base/task/task_runner.h"
+#include "base/time/time.h"
+#include "components/policy/core/common/cloud/enterprise_metrics.h"
+#include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/policy/core/common/policy_service.h"
 #include "components/policy/core/common/policy_types.h"
@@ -22,8 +25,71 @@
 
 namespace policy {
 
-const int PolicyStatisticsCollector::kStatisticsUpdateRate =
-    24 * 60 * 60 * 1000;  // 24 hours.
+namespace {
+
+constexpr char kPoliciesSourceMetricsName[] = "Enterprise.Policies.Sources";
+
+constexpr const char* kCBCMEnrollmentPolicies[] = {
+    "CloudManagementEnrollmentToken", "CloudManagementEnrollmentMandatory"};
+
+enum SimplePolicySource {
+  kNone = 0,
+  kCloud = 1 << 0,
+  kPlatform = 1 << 1,
+  kMerge = kCloud | kPlatform,
+  kEnrollment = 1 << 2,
+};
+
+SimplePolicySource SimplifyPolicySource(PolicySource source,
+                                        const std::string& policy_name) {
+  switch (source) {
+    case POLICY_SOURCE_CLOUD:
+    case POLICY_SOURCE_CLOUD_FROM_ASH:
+      return kCloud;
+    case POLICY_SOURCE_PLATFORM:
+    case POLICY_SOURCE_ACTIVE_DIRECTORY:
+      // Adjust for enrollment policies which can never be set from cloud.
+      // Count them as cloud policy so that a device is considered as cloud
+      // managed even if there is enrollment token only.
+      for (const char* enrollment_policy : kCBCMEnrollmentPolicies) {
+        if (policy_name == enrollment_policy)
+          return kEnrollment;
+      }
+      return kPlatform;
+    case POLICY_SOURCE_MERGED:
+      return kMerge;
+    default:
+      // Other sources are only used for speicial cases and will not be counted.
+      return kNone;
+  }
+}
+
+void RecordPoliciesSources(SimplePolicySource source) {
+  if ((source & kMerge) == kMerge) {
+    base::UmaHistogramEnumeration(kPoliciesSourceMetricsName,
+                                  PoliciesSources::kHybrid);
+  } else if (source & kPlatform) {
+    base::UmaHistogramEnumeration(kPoliciesSourceMetricsName,
+                                  PoliciesSources::kPlatformOnly);
+  } else if (source & kCloud) {
+    if (source & kEnrollment) {
+      base::UmaHistogramEnumeration(
+          kPoliciesSourceMetricsName,
+          PoliciesSources::kCloudOnlyExceptEnrollment);
+    } else {
+      base::UmaHistogramEnumeration(kPoliciesSourceMetricsName,
+                                    PoliciesSources::kCloudOnly);
+    }
+  } else if (source & kEnrollment) {
+    base::UmaHistogramEnumeration(kPoliciesSourceMetricsName,
+                                  PoliciesSources::kEnrollmentOnly);
+  }
+}
+
+}  // namespace
+
+const base::TimeDelta PolicyStatisticsCollector::kStatisticsUpdateRate =
+    base::Days(1);
 
 PolicyStatisticsCollector::PolicyStatisticsCollector(
     const GetChromePolicyDetailsCallback& get_details,
@@ -35,22 +101,19 @@
       chrome_schema_(chrome_schema),
       policy_service_(policy_service),
       prefs_(prefs),
-      task_runner_(task_runner) {
-}
+      task_runner_(task_runner) {}
 
-PolicyStatisticsCollector::~PolicyStatisticsCollector() {
-}
+PolicyStatisticsCollector::~PolicyStatisticsCollector() = default;
 
 void PolicyStatisticsCollector::Initialize() {
-  using base::Time;
-
-  base::TimeDelta update_rate = base::Milliseconds(kStatisticsUpdateRate);
-  Time last_update = prefs_->GetTime(policy_prefs::kLastPolicyStatisticsUpdate);
-  base::TimeDelta delay = std::max(Time::Now() - last_update, base::Days(0));
-  if (delay >= update_rate)
+  base::Time last_update =
+      prefs_->GetTime(policy_prefs::kLastPolicyStatisticsUpdate);
+  base::TimeDelta delay =
+      std::max(base::Time::Now() - last_update, base::TimeDelta());
+  if (delay >= kStatisticsUpdateRate)
     CollectStatistics();
   else
-    ScheduleUpdate(update_rate - delay);
+    ScheduleUpdate(kStatisticsUpdateRate - delay);
 }
 
 // static
@@ -80,22 +143,25 @@
   const PolicyMap& policies = policy_service_->GetPolicies(
       PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
 
+  int source = kNone;
   // Collect statistics.
   for (Schema::Iterator it(chrome_schema_.GetPropertiesIterator());
        !it.IsAtEnd(); it.Advance()) {
-    if (policies.Get(it.key())) {
-      const PolicyDetails* details = get_details_.Run(it.key());
-      if (details) {
-        RecordPolicyUse(details->id, kDefault);
-        if (policies.Get(it.key())->level == POLICY_LEVEL_MANDATORY) {
-          RecordPolicyUse(details->id, kMandatory);
-        } else {
-          RecordPolicyUse(details->id, kRecommended);
-        }
+    const PolicyMap::Entry* policy_entry = policies.Get(it.key());
+    if (!policy_entry)
+      continue;
+    const PolicyDetails* details = get_details_.Run(it.key());
+    if (details) {
+      RecordPolicyUse(details->id, kDefault);
+      if (policies.Get(it.key())->level == POLICY_LEVEL_MANDATORY) {
+        RecordPolicyUse(details->id, kMandatory);
       } else {
-        NOTREACHED();
+        RecordPolicyUse(details->id, kRecommended);
       }
+    } else {
+      NOTREACHED();
     }
+    source |= SimplifyPolicySource(policy_entry->source, it.key());
   }
 
   for (size_t i = 0; i < kPolicyAtomicGroupMappingsLength; ++i) {
@@ -114,9 +180,11 @@
     }
   }
 
+  RecordPoliciesSources(static_cast<SimplePolicySource>(source));
+
   // Take care of next update.
   prefs_->SetTime(policy_prefs::kLastPolicyStatisticsUpdate, base::Time::Now());
-  ScheduleUpdate(base::Milliseconds(kStatisticsUpdateRate));
+  ScheduleUpdate(kStatisticsUpdateRate);
 }
 
 void PolicyStatisticsCollector::ScheduleUpdate(base::TimeDelta delay) {
@@ -125,4 +193,4 @@
   task_runner_->PostDelayedTask(FROM_HERE, update_callback_.callback(), delay);
 }
 
-}  // namespace policy
\ No newline at end of file
+}  // namespace policy
diff --git a/components/policy/core/common/policy_statistics_collector.h b/components/policy/core/common/policy_statistics_collector.h
index 5f5552b..0d13321 100644
--- a/components/policy/core/common/policy_statistics_collector.h
+++ b/components/policy/core/common/policy_statistics_collector.h
@@ -32,11 +32,20 @@
   kIgnoredByAtomicGroup,
 };
 
+enum class PoliciesSources {
+  kCloudOnly = 0,
+  kCloudOnlyExceptEnrollment = 1,
+  kPlatformOnly = 2,
+  kHybrid = 3,
+  kEnrollmentOnly = 4,
+  kMaxValue = kEnrollmentOnly,
+};
+
 // Manages regular updates of policy usage UMA histograms.
 class POLICY_EXPORT PolicyStatisticsCollector {
  public:
   // Policy usage statistics update rate, in milliseconds.
-  static const int kStatisticsUpdateRate;
+  static const base::TimeDelta kStatisticsUpdateRate;
 
   // Neither |policy_service| nor |prefs| can be NULL and must stay valid
   // throughout the lifetime of PolicyStatisticsCollector.
@@ -55,11 +64,8 @@
 
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
- protected:
-  // protected virtual for mocking.
-  virtual void RecordPolicyUse(int id, Condition condition);
-
  private:
+  void RecordPolicyUse(int id, Condition condition);
   void CollectStatistics();
   void ScheduleUpdate(base::TimeDelta delay);
 
@@ -75,4 +81,4 @@
 
 }  // namespace policy
 
-#endif  // COMPONENTS_POLICY_CORE_COMMON_POLICY_STATISTICS_COLLECTOR_H_
\ No newline at end of file
+#endif  // COMPONENTS_POLICY_CORE_COMMON_POLICY_STATISTICS_COLLECTOR_H_
diff --git a/components/policy/core/common/policy_statistics_collector_unittest.cc b/components/policy/core/common/policy_statistics_collector_unittest.cc
index 422ddc68..31a3816 100644
--- a/components/policy/core/common/policy_statistics_collector_unittest.cc
+++ b/components/policy/core/common/policy_statistics_collector_unittest.cc
@@ -37,25 +37,34 @@
 const char kTestPolicy2[] = "Test Policy 2";
 const char* kTestPolicy3 = key::kExtensionInstallBlocklist;
 
+const char kEnrollmentTokenPolicy[] = "CloudManagementEnrollmentToken";
+const char kEnrollmentOptionPolicy[] = "CloudManagementEnrollmentMandatory";
+
 const int kTestPolicy1Id = 42;
 const int kTestPolicy2Id = 123;
 const int kTestPolicy3Id = 32;
+const int kEnrollmentTokenPolicyId = 510;
+const int kEnrollmentOptionPolicyId = 505;
 
-const char kTestChromeSchema[] =
-    "{"
-    "  \"type\": \"object\","
-    "  \"properties\": {"
-    "    \"Test Policy 1\": { \"type\": \"string\" },"
-    "    \"Test Policy 2\": { \"type\": \"string\" },"
-    "    \"ExtensionInstallBlocklist\": { \"type\": \"string\" },"
-    "  }"
-    "}";
+const char kTestChromeSchema[] = R"(
+    {
+      "type": "object",
+      "properties": {
+        "Test Policy 1": { "type": "boolean" },
+        "Test Policy 2": { "type": "boolean" },
+        "ExtensionInstallBlocklist": { "type": "boolean" },
+        "CloudManagementEnrollmentToken": { "type": "boolean" },
+        "CloudManagementEnrollmentMandatory": { "type": "boolean" },
+      }
+    })";
 
 const PolicyDetails kTestPolicyDetails[] = {
     // is_deprecated is_future is_device_policy id  max_external_data_size
     {false, false, false, kTestPolicy1Id, 0},
     {false, false, false, kTestPolicy2Id, 0},
     {false, false, false, kTestPolicy3Id, 0},
+    {false, false, false, kEnrollmentTokenPolicyId, 0},
+    {false, false, false, kEnrollmentOptionPolicyId, 0},
 };
 
 }  // namespace
@@ -63,9 +72,7 @@
 class PolicyStatisticsCollectorTest : public testing::Test {
  protected:
   PolicyStatisticsCollectorTest()
-      : update_delay_(base::Milliseconds(
-            PolicyStatisticsCollector::kStatisticsUpdateRate)),
-        task_runner_(new base::TestSimpleTaskRunner()) {}
+      : task_runner_(new base::TestSimpleTaskRunner()) {}
 
   void SetUp() override {
     std::string error;
@@ -75,18 +82,17 @@
     policy_details_.SetDetails(kTestPolicy1, &kTestPolicyDetails[0]);
     policy_details_.SetDetails(kTestPolicy2, &kTestPolicyDetails[1]);
     policy_details_.SetDetails(kTestPolicy3, &kTestPolicyDetails[2]);
+    policy_details_.SetDetails(kEnrollmentTokenPolicy, &kTestPolicyDetails[3]);
+    policy_details_.SetDetails(kEnrollmentOptionPolicy, &kTestPolicyDetails[4]);
 
     prefs_.registry()->RegisterInt64Pref(
         policy_prefs::kLastPolicyStatisticsUpdate, 0);
 
     // Set up default function behaviour.
-    EXPECT_CALL(policy_service_,
-                GetPolicies(PolicyNamespace(POLICY_DOMAIN_CHROME,
-                                            std::string())))
+    EXPECT_CALL(policy_service_, GetPolicies(PolicyNamespace(
+                                     POLICY_DOMAIN_CHROME, std::string())))
         .WillRepeatedly(ReturnRef(policy_map_));
 
-    // Arbitrary negative value (so it'll be different from |update_delay_|).
-    last_delay_ = base::Days(-1);
     policy_map_.Clear();
     policy_statistics_collector_ = std::make_unique<PolicyStatisticsCollector>(
         policy_details_.GetCallback(), chrome_schema_, &policy_service_,
@@ -96,7 +102,12 @@
   void SetPolicy(const std::string& name,
                  PolicyLevel level = POLICY_LEVEL_MANDATORY) {
     policy_map_.Set(name, level, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
-                    base::Value(true), nullptr);
+                    base::Value(true), /*external_data_fetcher=*/nullptr);
+  }
+
+  void SetPolicy(const std::string& name, PolicySource source) {
+    policy_map_.Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, source,
+                    base::Value(true), /*external_data_fetcher=*/nullptr);
   }
 
   void SetPolicyIgnoredByAtomicGroup(const std::string& name) {
@@ -113,10 +124,6 @@
     return task_runner_->NextPendingTaskDelay();
   }
 
-  const base::TimeDelta update_delay_;
-
-  base::TimeDelta last_delay_;
-
   PolicyDetailsMap policy_details_;
   Schema chrome_schema_;
   TestingPrefServiceSimple prefs_;
@@ -129,12 +136,18 @@
   base::HistogramTester histogram_tester_;
 };
 
+TEST_F(PolicyStatisticsCollectorTest, NoPolicy) {
+  policy_statistics_collector_->Initialize();
+
+  histogram_tester_.ExpectTotalCount("Enterprise.Policies.Mandatory", 0);
+  histogram_tester_.ExpectTotalCount("Enterprise.Policies.Recommended", 0);
+  histogram_tester_.ExpectTotalCount("Enterprise.Policies", 0);
+  histogram_tester_.ExpectTotalCount("Enterprise.Policies.Sources", 0);
+}
+
 TEST_F(PolicyStatisticsCollectorTest, CollectPending) {
   SetPolicy(kTestPolicy1, POLICY_LEVEL_MANDATORY);
 
-  prefs_.SetTime(policy_prefs::kLastPolicyStatisticsUpdate,
-                 base::Time::Now() - update_delay_);
-
   policy_statistics_collector_->Initialize();
 
   histogram_tester_.ExpectBucketCount("Enterprise.Policies", kTestPolicy1Id, 1);
@@ -159,8 +172,9 @@
 TEST_F(PolicyStatisticsCollectorTest, CollectLater) {
   SetPolicy(kTestPolicy1, POLICY_LEVEL_MANDATORY);
 
-  prefs_.SetTime(policy_prefs::kLastPolicyStatisticsUpdate,
-                 base::Time::Now() - update_delay_ / 2);
+  prefs_.SetTime(
+      policy_prefs::kLastPolicyStatisticsUpdate,
+      base::Time::Now() - PolicyStatisticsCollector::kStatisticsUpdateRate / 2);
 
   policy_statistics_collector_->Initialize();
 
@@ -173,9 +187,6 @@
   SetPolicy(kTestPolicy1, POLICY_LEVEL_MANDATORY);
   SetPolicy(kTestPolicy2, POLICY_LEVEL_RECOMMENDED);
 
-  prefs_.SetTime(policy_prefs::kLastPolicyStatisticsUpdate,
-                 base::Time::Now() - update_delay_);
-
   policy_statistics_collector_->Initialize();
 
   histogram_tester_.ExpectBucketCount("Enterprise.Policies", kTestPolicy1Id, 1);
@@ -196,9 +207,6 @@
 
   DCHECK(extensions);
 
-  prefs_.SetTime(policy_prefs::kLastPolicyStatisticsUpdate,
-                 base::Time::Now() - update_delay_);
-
   policy_statistics_collector_->Initialize();
 
   histogram_tester_.ExpectUniqueSample(
@@ -208,9 +216,6 @@
 TEST_F(PolicyStatisticsCollectorTest, MandatoryPolicy) {
   SetPolicy(kTestPolicy1, POLICY_LEVEL_MANDATORY);
 
-  prefs_.SetTime(policy_prefs::kLastPolicyStatisticsUpdate,
-                 base::Time::Now() - update_delay_);
-
   policy_statistics_collector_->Initialize();
 
   histogram_tester_.ExpectUniqueSample("Enterprise.Policies.Mandatory",
@@ -221,9 +226,6 @@
 TEST_F(PolicyStatisticsCollectorTest, RecommendedPolicy) {
   SetPolicy(kTestPolicy2, POLICY_LEVEL_RECOMMENDED);
 
-  prefs_.SetTime(policy_prefs::kLastPolicyStatisticsUpdate,
-                 base::Time::Now() - update_delay_);
-
   policy_statistics_collector_->Initialize();
 
   histogram_tester_.ExpectUniqueSample("Enterprise.Policies.Recommended",
@@ -231,4 +233,57 @@
   histogram_tester_.ExpectTotalCount("Enterprise.Policies.Mandatory", 0);
 }
 
+TEST_F(PolicyStatisticsCollectorTest, CloudOnly) {
+  SetPolicy(kTestPolicy1, POLICY_SOURCE_CLOUD);
+  SetPolicy(kTestPolicy2, POLICY_SOURCE_CLOUD_FROM_ASH);
+
+  policy_statistics_collector_->Initialize();
+
+  histogram_tester_.ExpectUniqueSample("Enterprise.Policies.Sources",
+                                       PoliciesSources::kCloudOnly, 1);
+}
+
+TEST_F(PolicyStatisticsCollectorTest, PlatformOnly) {
+  SetPolicy(kTestPolicy1, POLICY_SOURCE_PLATFORM);
+  SetPolicy(kTestPolicy2, POLICY_SOURCE_ACTIVE_DIRECTORY);
+  SetPolicy(kEnrollmentTokenPolicy, POLICY_SOURCE_PLATFORM);
+
+  policy_statistics_collector_->Initialize();
+
+  histogram_tester_.ExpectUniqueSample("Enterprise.Policies.Sources",
+                                       PoliciesSources::kPlatformOnly, 1);
+}
+
+TEST_F(PolicyStatisticsCollectorTest, Hybrid) {
+  SetPolicy(kTestPolicy1, POLICY_SOURCE_PLATFORM);
+  SetPolicy(kTestPolicy2, POLICY_SOURCE_CLOUD);
+
+  policy_statistics_collector_->Initialize();
+
+  histogram_tester_.ExpectUniqueSample("Enterprise.Policies.Sources",
+                                       PoliciesSources::kHybrid, 1);
+}
+
+TEST_F(PolicyStatisticsCollectorTest, CloudExcepptEnrollment) {
+  SetPolicy(kTestPolicy1, POLICY_SOURCE_CLOUD);
+  SetPolicy(kEnrollmentTokenPolicy, POLICY_SOURCE_PLATFORM);
+  SetPolicy(kEnrollmentOptionPolicy, POLICY_SOURCE_PLATFORM);
+
+  policy_statistics_collector_->Initialize();
+
+  histogram_tester_.ExpectUniqueSample(
+      "Enterprise.Policies.Sources",
+      PoliciesSources::kCloudOnlyExceptEnrollment, 1);
+}
+
+TEST_F(PolicyStatisticsCollectorTest, EnrollmentOnly) {
+  SetPolicy(kEnrollmentTokenPolicy, POLICY_SOURCE_PLATFORM);
+  SetPolicy(kEnrollmentOptionPolicy, POLICY_SOURCE_PLATFORM);
+
+  policy_statistics_collector_->Initialize();
+
+  histogram_tester_.ExpectUniqueSample("Enterprise.Policies.Sources",
+                                       PoliciesSources::kEnrollmentOnly, 1);
+}
+
 }  // namespace policy
diff --git a/components/prefs/android/BUILD.gn b/components/prefs/android/BUILD.gn
index 4d5e50fd..1a16c726 100644
--- a/components/prefs/android/BUILD.gn
+++ b/components/prefs/android/BUILD.gn
@@ -12,6 +12,7 @@
   sources = [ "java/src/org/chromium/components/prefs/PrefService.java" ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/components/privacy_sandbox/privacy_sandbox_settings.cc b/components/privacy_sandbox/privacy_sandbox_settings.cc
index 3f43dc20..9eeffe96 100644
--- a/components/privacy_sandbox/privacy_sandbox_settings.cc
+++ b/components/privacy_sandbox/privacy_sandbox_settings.cc
@@ -338,6 +338,18 @@
   return allowed_parties;
 }
 
+bool PrivacySandboxSettings::IsSharedStorageAllowed(
+    const url::Origin& top_frame_origin,
+    const url::Origin& accessing_origin) const {
+  ContentSettingsForOneType cookie_settings;
+  cookie_settings_->GetCookieSettings(&cookie_settings);
+
+  // Ensures that Shared Storage is only allowed if both Privacy Sandbox is
+  // enabled and full cookie access is enabled for this context.
+  return IsPrivacySandboxEnabledForContext(accessing_origin.GetURL(),
+                                           top_frame_origin, cookie_settings);
+}
+
 bool PrivacySandboxSettings::IsPrivacySandboxEnabled() const {
   // If the delegate is restricting access, or indicates confirmation has not
   // occurred, the Privacy Sandbox is disabled.
diff --git a/components/privacy_sandbox/privacy_sandbox_settings.h b/components/privacy_sandbox/privacy_sandbox_settings.h
index b1a4b3f..289b9c2 100644
--- a/components/privacy_sandbox/privacy_sandbox_settings.h
+++ b/components/privacy_sandbox/privacy_sandbox_settings.h
@@ -155,6 +155,12 @@
       const url::Origin& top_frame_origin,
       const std::vector<GURL>& auction_parties);
 
+  // Determines whether Shared Storage is allowable in a particular context.
+  // `top_frame_origin` can be the same as `accessing_origin` in the case of a
+  // top-level document calling Shared Storage.
+  bool IsSharedStorageAllowed(const url::Origin& top_frame_origin,
+                              const url::Origin& accessing_origin) const;
+
   // Returns whether the profile has the Privacy Sandbox enabled. This consults
   // the main preference, as well as the delegate to check whether the sandbox
   // is restricted, or has not been confirmed.  It does not consider any cookie
diff --git a/components/privacy_sandbox/privacy_sandbox_settings_unittest.cc b/components/privacy_sandbox/privacy_sandbox_settings_unittest.cc
index b9246e3..d45cdd7 100644
--- a/components/privacy_sandbox/privacy_sandbox_settings_unittest.cc
+++ b/components/privacy_sandbox/privacy_sandbox_settings_unittest.cc
@@ -141,6 +141,10 @@
                 {GURL("https://embedded.com"),
                  GURL("https://another-embedded.com")}));
 
+  EXPECT_FALSE(privacy_sandbox_settings()->IsSharedStorageAllowed(
+      url::Origin::Create(GURL("https://test.com")),
+      url::Origin::Create(GURL("https://embedded.com"))));
+
   // An allow default or exception, whether via user or policy, should not
   // override the preference value.
   privacy_sandbox_test_util::SetupTestState(
@@ -185,6 +189,10 @@
                 url::Origin::Create(GURL("https://test.com")),
                 {GURL("https://embedded.com"),
                  GURL("https://another-embedded.com")}));
+
+  EXPECT_FALSE(privacy_sandbox_settings()->IsSharedStorageAllowed(
+      url::Origin::Create(GURL("https://test.com")),
+      url::Origin::Create(GURL("https://embedded.com"))));
 }
 
 TEST_P(PrivacySandboxSettingsTest, CookieExceptionsApply) {
@@ -225,6 +233,10 @@
                 {GURL("https://embedded.com"),
                  GURL("https://another-embedded.com")}));
 
+  EXPECT_FALSE(privacy_sandbox_settings()->IsSharedStorageAllowed(
+      url::Origin::Create(GURL("https://test.com")),
+      url::Origin::Create(GURL("https://embedded.com"))));
+
   // The default managed content setting should apply, overriding any user ones,
   // and disabling Topics calculations.
   privacy_sandbox_test_util::SetupTestState(
@@ -263,6 +275,10 @@
                 {GURL("https://embedded.com"),
                  GURL("https://another-embedded.com")}));
 
+  EXPECT_FALSE(privacy_sandbox_settings()->IsSharedStorageAllowed(
+      url::Origin::Create(GURL("https://test.com")),
+      url::Origin::Create(GURL("https://embedded.com"))));
+
   // Managed content setting exceptions should override both the privacy
   // sandbox pref and any user settings.
   privacy_sandbox_test_util::SetupTestState(
@@ -313,6 +329,10 @@
                 {GURL("https://embedded.com"),
                  GURL("https://another-embedded.com")}));
 
+  EXPECT_FALSE(privacy_sandbox_settings()->IsSharedStorageAllowed(
+      url::Origin::Create(GURL("https://test.com")),
+      url::Origin::Create(GURL("https://embedded.com"))));
+
   // A less specific block exception should not override a more specific allow
   // exception. The effective content setting in this scenario is still allow,
   // even though a block exception exists.
@@ -377,6 +397,10 @@
                 {GURL("https://embedded.com"),
                  GURL("https://another-embedded.com")}));
 
+  EXPECT_TRUE(privacy_sandbox_settings()->IsSharedStorageAllowed(
+      url::Origin::Create(GURL("https://another-test.com")),
+      url::Origin::Create(GURL("https://embedded.com"))));
+
   // Exceptions which specify a wildcard top frame origin should match both
   // empty top frames and non empty top frames.
   privacy_sandbox_test_util::SetupTestState(
@@ -412,6 +436,10 @@
                 url::Origin::Create(GURL("https://test.com")),
                 {GURL("https://embedded.com"),
                  GURL("https://another-embedded.com")}));
+
+  EXPECT_FALSE(privacy_sandbox_settings()->IsSharedStorageAllowed(
+      url::Origin::Create(GURL("https://test.com")),
+      url::Origin::Create(GURL("https://embedded.com"))));
 }
 
 TEST_P(PrivacySandboxSettingsTest, ThirdPartyCookies) {
@@ -447,6 +475,10 @@
                 {GURL("https://embedded.com"),
                  GURL("https://another-embedded.com")}));
 
+  EXPECT_FALSE(privacy_sandbox_settings()->IsSharedStorageAllowed(
+      url::Origin::Create(GURL("https://test.com")),
+      url::Origin::Create(GURL("https://embedded.com"))));
+
   // Privacy Sandbox APIs should be disabled if all cookies are blocked.
   privacy_sandbox_test_util::SetupTestState(
       prefs(), host_content_settings_map(),
@@ -479,6 +511,10 @@
                 {GURL("https://embedded.com"),
                  GURL("https://another-embedded.com")}));
 
+  EXPECT_FALSE(privacy_sandbox_settings()->IsSharedStorageAllowed(
+      url::Origin::Create(GURL("https://test.com")),
+      url::Origin::Create(GURL("https://embedded.com"))));
+
   // Privacy Sandbox APIs should be disabled if the privacy sandbox is disabled,
   // regardless of other cookie settings.
   privacy_sandbox_test_util::SetupTestState(
@@ -515,6 +551,10 @@
                 url::Origin::Create(GURL("https://test.com")),
                 {GURL("https://embedded.com"),
                  GURL("https://another-embedded.com")}));
+
+  EXPECT_FALSE(privacy_sandbox_settings()->IsSharedStorageAllowed(
+      url::Origin::Create(GURL("https://test.com")),
+      url::Origin::Create(GURL("https://embedded.com"))));
 }
 
 TEST_P(PrivacySandboxSettingsTest, IsPrivacySandboxEnabled) {
diff --git a/components/query_tiles/BUILD.gn b/components/query_tiles/BUILD.gn
index 3eb0305..c57d6b51 100644
--- a/components/query_tiles/BUILD.gn
+++ b/components/query_tiles/BUILD.gn
@@ -101,6 +101,7 @@
     deps = [
       ":query_tile_java",
       "//base:base_java",
+      "//build/android:build_java",
       "//components/browser_ui/widget/android:java",
       "//third_party/androidx:androidx_annotation_annotation_java",
       "//ui/android:ui_java",
@@ -141,6 +142,7 @@
       ":test_support_java",
       "//base:base_java",
       "//base:base_junit_test_support",
+      "//build/android:build_java",
       "//third_party/android_deps:robolectric_all_java",
       "//third_party/junit",
     ]
diff --git a/components/safe_browsing/android/BUILD.gn b/components/safe_browsing/android/BUILD.gn
index 32b6836..eb463478 100644
--- a/components/safe_browsing/android/BUILD.gn
+++ b/components/safe_browsing/android/BUILD.gn
@@ -8,6 +8,7 @@
 android_library("safe_browsing_java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/components/search_engines/android/BUILD.gn b/components/search_engines/android/BUILD.gn
index 810bbab..309efc63 100644
--- a/components/search_engines/android/BUILD.gn
+++ b/components/search_engines/android/BUILD.gn
@@ -7,6 +7,7 @@
 android_library("java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//url:gurl_java",
diff --git a/components/security_interstitials/content/android/BUILD.gn b/components/security_interstitials/content/android/BUILD.gn
index 99edd0d..222c07f 100644
--- a/components/security_interstitials/content/android/BUILD.gn
+++ b/components/security_interstitials/content/android/BUILD.gn
@@ -20,6 +20,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
 }
diff --git a/components/security_state/content/android/BUILD.gn b/components/security_state/content/android/BUILD.gn
index 787f71b..ed12841 100644
--- a/components/security_state/content/android/BUILD.gn
+++ b/components/security_state/content/android/BUILD.gn
@@ -26,6 +26,7 @@
   ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/security_state/core:security_state_enums_java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/segmentation_platform/internal/BUILD.gn b/components/segmentation_platform/internal/BUILD.gn
index eadf6de5..000e95a 100644
--- a/components/segmentation_platform/internal/BUILD.gn
+++ b/components/segmentation_platform/internal/BUILD.gn
@@ -303,6 +303,7 @@
 
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//components/optimization_guide/proto:optimization_guide_proto_java",
       "//components/segmentation_platform/public:public_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/signin/public/android/BUILD.gn b/components/signin/public/android/BUILD.gn
index f6cd0621..d29d8ab 100644
--- a/components/signin/public/android/BUILD.gn
+++ b/components/signin/public/android/BUILD.gn
@@ -5,6 +5,7 @@
     "$google_play_services_package:google_play_services_auth_base_java",
     "$google_play_services_package:google_play_services_base_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/externalauth/android:java",
     "//net/android:net_java",
     "//third_party/android_deps:chromium_play_services_availability_java",
@@ -132,6 +133,7 @@
     ":signin_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
@@ -166,6 +168,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//components/externalauth/android:google_delegate_public_impl_java",
     "//components/externalauth/android:java",
     "//testing/android/junit:junit_test_support",
diff --git a/components/site_engagement/content/android/BUILD.gn b/components/site_engagement/content/android/BUILD.gn
index 851994a..4cfa823f 100644
--- a/components/site_engagement/content/android/BUILD.gn
+++ b/components/site_engagement/content/android/BUILD.gn
@@ -8,6 +8,7 @@
   sources = [ "java/src/org/chromium/components/site_engagement/SiteEngagementService.java" ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_full_java",
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/components/spellcheck/browser/android/BUILD.gn b/components/spellcheck/browser/android/BUILD.gn
index 6c847d7..991bed4 100644
--- a/components/spellcheck/browser/android/BUILD.gn
+++ b/components/spellcheck/browser/android/BUILD.gn
@@ -9,7 +9,10 @@
 }
 
 android_library("java") {
-  deps = [ "//base:base_java" ]
+  deps = [
+    "//base:base_java",
+    "//build/android:build_java",
+  ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 
   sources = [ "java/src/org/chromium/components/spellcheck/SpellCheckerSessionBridge.java" ]
diff --git a/components/subresource_filter/android/BUILD.gn b/components/subresource_filter/android/BUILD.gn
index 88300eb..17520df1 100644
--- a/components/subresource_filter/android/BUILD.gn
+++ b/components/subresource_filter/android/BUILD.gn
@@ -22,6 +22,7 @@
     ":java_resources",
     ":subresource_filter_jni_headers",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/infobars/android:infobar_android_enums_java",
     "//components/infobars/android:java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/sync/android/BUILD.gn b/components/sync/android/BUILD.gn
index 0c1a5d7..9be36c3 100644
--- a/components/sync/android/BUILD.gn
+++ b/components/sync/android/BUILD.gn
@@ -14,9 +14,7 @@
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   srcjar_deps = [ ":java_enums" ]
-  sources = [
-    "java/src/org/chromium/components/sync/Passphrase.java",
-  ]
+  sources = [ "java/src/org/chromium/components/sync/Passphrase.java" ]
 }
 
 java_cpp_enum("java_enums") {
diff --git a/components/thin_webview/internal/BUILD.gn b/components/thin_webview/internal/BUILD.gn
index 9a12e7f..5bc05260 100644
--- a/components/thin_webview/internal/BUILD.gn
+++ b/components/thin_webview/internal/BUILD.gn
@@ -36,6 +36,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/embedder_support/android:web_contents_delegate_java",
     "//components/thin_webview:java",
     "//content/public/android:content_java",
diff --git a/components/translate/content/android/BUILD.gn b/components/translate/content/android/BUILD.gn
index 22adfa6..e8fff1dc 100644
--- a/components/translate/content/android/BUILD.gn
+++ b/components/translate/content/android/BUILD.gn
@@ -41,6 +41,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/widget/android:java",
     "//components/messages/android:java",
     "//content/public/android:content_java",
diff --git a/components/ukm/android/BUILD.gn b/components/ukm/android/BUILD.gn
index 7a98d7a..d15e4943 100644
--- a/components/ukm/android/BUILD.gn
+++ b/components/ukm/android/BUILD.gn
@@ -9,6 +9,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
diff --git a/components/url_formatter/android/BUILD.gn b/components/url_formatter/android/BUILD.gn
index 02ebbef4..6062c64 100644
--- a/components/url_formatter/android/BUILD.gn
+++ b/components/url_formatter/android/BUILD.gn
@@ -7,6 +7,7 @@
 android_library("url_formatter_java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//url:gurl_java",
     "//url:origin_java",
diff --git a/components/url_matcher/url_matcher_factory.cc b/components/url_matcher/url_matcher_factory.cc
index 0c94822..ca5b7cc4 100644
--- a/components/url_matcher/url_matcher_factory.cc
+++ b/components/url_matcher/url_matcher_factory.cc
@@ -108,17 +108,16 @@
 scoped_refptr<URLMatcherConditionSet>
 URLMatcherFactory::CreateFromURLFilterDictionary(
     URLMatcherConditionFactory* url_matcher_condition_factory,
-    const base::DictionaryValue* url_filter_dict,
+    const base::Value::Dict& url_filter_dict,
     URLMatcherConditionSet::ID id,
     std::string* error) {
   std::unique_ptr<URLMatcherSchemeFilter> url_matcher_schema_filter;
   std::unique_ptr<URLMatcherPortFilter> url_matcher_port_filter;
   URLMatcherConditionSet::Conditions url_matcher_conditions;
 
-  for (base::DictionaryValue::Iterator iter(*url_filter_dict);
-       !iter.IsAtEnd(); iter.Advance()) {
-    const std::string& condition_attribute_name = iter.key();
-    const base::Value& condition_attribute_value = iter.value();
+  for (const auto iter : url_filter_dict) {
+    const std::string& condition_attribute_name = iter.first;
+    const base::Value& condition_attribute_value = iter.second;
     if (IsURLMatcherConditionAttribute(condition_attribute_name)) {
       // Handle {host, path, ...}{Prefix, Suffix, Contains, Equals}.
       URLMatcherCondition url_matcher_condition =
diff --git a/components/url_matcher/url_matcher_factory.h b/components/url_matcher/url_matcher_factory.h
index 4bb3e798..8ae9b0d2 100644
--- a/components/url_matcher/url_matcher_factory.h
+++ b/components/url_matcher/url_matcher_factory.h
@@ -8,14 +8,10 @@
 #include <memory>
 #include <string>
 
+#include "base/values.h"
 #include "components/url_matcher/url_matcher.h"
 #include "components/url_matcher/url_matcher_export.h"
 
-namespace base {
-class DictionaryValue;
-class Value;
-}
-
 namespace url_matcher {
 
 class URL_MATCHER_EXPORT URLMatcherFactory {
@@ -36,7 +32,7 @@
   // URLMatcherFactory. Otherwise you leak memory.
   static scoped_refptr<URLMatcherConditionSet> CreateFromURLFilterDictionary(
       URLMatcherConditionFactory* url_matcher_condition_factory,
-      const base::DictionaryValue* url_filter_dict,
+      const base::Value::Dict& url_filter_dict,
       URLMatcherConditionSet::ID id,
       std::string* error);
 
diff --git a/components/url_matcher/url_matcher_factory_unittest.cc b/components/url_matcher/url_matcher_factory_unittest.cc
index aa5c8fe7..eef54358 100644
--- a/components/url_matcher/url_matcher_factory_unittest.cc
+++ b/components/url_matcher/url_matcher_factory_unittest.cc
@@ -27,21 +27,21 @@
   scoped_refptr<URLMatcherConditionSet> result;
 
   // Invalid key: {"invalid": "foobar"}
-  base::DictionaryValue invalid_condition;
-  invalid_condition.SetStringKey("invalid", "foobar");
+  base::Value::Dict invalid_condition;
+  invalid_condition.Set("invalid", "foobar");
 
   // Invalid value type: {"hostSuffix": []}
-  base::DictionaryValue invalid_condition2;
-  invalid_condition2.SetKey(keys::kHostSuffixKey,
-                            base::Value(base::Value::Type::LIST));
+  base::Value::Dict invalid_condition2;
+  invalid_condition2.Set(keys::kHostSuffixKey,
+                         base::Value(base::Value::Type::LIST));
 
   // Invalid regex value: {"urlMatches": "*"}
-  base::DictionaryValue invalid_condition3;
-  invalid_condition3.SetStringKey(keys::kURLMatchesKey, "*");
+  base::Value::Dict invalid_condition3;
+  invalid_condition3.Set(keys::kURLMatchesKey, "*");
 
   // Invalid regex value: {"originAndPathMatches": "*"}
-  base::DictionaryValue invalid_condition4;
-  invalid_condition4.SetStringKey(keys::kOriginAndPathMatchesKey, "*");
+  base::Value::Dict invalid_condition4;
+  invalid_condition4.Set(keys::kOriginAndPathMatchesKey, "*");
 
   // Valid values:
   // {
@@ -62,43 +62,43 @@
   base::Value scheme_list(base::Value::Type::LIST);
   scheme_list.Append("http");
 
-  base::DictionaryValue valid_condition;
-  valid_condition.SetStringKey(keys::kHostSuffixKey, "example.com");
-  valid_condition.SetStringKey(keys::kHostPrefixKey, "www");
-  valid_condition.SetKey(keys::kPortsKey, std::move(port_ranges));
-  valid_condition.SetKey(keys::kSchemesKey, std::move(scheme_list));
+  base::Value::Dict valid_condition;
+  valid_condition.Set(keys::kHostSuffixKey, "example.com");
+  valid_condition.Set(keys::kHostPrefixKey, "www");
+  valid_condition.Set(keys::kPortsKey, std::move(port_ranges));
+  valid_condition.Set(keys::kSchemesKey, std::move(scheme_list));
 
   // Test wrong condition name passed.
   error.clear();
   result = URLMatcherFactory::CreateFromURLFilterDictionary(
-      matcher.condition_factory(), &invalid_condition, 1, &error);
+      matcher.condition_factory(), invalid_condition, 1, &error);
   EXPECT_FALSE(error.empty());
   EXPECT_FALSE(result);
 
   // Test wrong datatype in hostSuffix.
   error.clear();
   result = URLMatcherFactory::CreateFromURLFilterDictionary(
-      matcher.condition_factory(), &invalid_condition2, 2, &error);
+      matcher.condition_factory(), invalid_condition2, 2, &error);
   EXPECT_FALSE(error.empty());
   EXPECT_FALSE(result);
 
   // Test invalid regex in urlMatches.
   error.clear();
   result = URLMatcherFactory::CreateFromURLFilterDictionary(
-      matcher.condition_factory(), &invalid_condition3, 3, &error);
+      matcher.condition_factory(), invalid_condition3, 3, &error);
   EXPECT_FALSE(error.empty());
   EXPECT_FALSE(result);
 
   error.clear();
   result = URLMatcherFactory::CreateFromURLFilterDictionary(
-      matcher.condition_factory(), &invalid_condition4, 4, &error);
+      matcher.condition_factory(), invalid_condition4, 4, &error);
   EXPECT_FALSE(error.empty());
   EXPECT_FALSE(result);
 
   // Test success.
   error.clear();
   result = URLMatcherFactory::CreateFromURLFilterDictionary(
-      matcher.condition_factory(), &valid_condition, 100, &error);
+      matcher.condition_factory(), valid_condition, 100, &error);
   EXPECT_EQ("", error);
   ASSERT_TRUE(result.get());
 
@@ -125,39 +125,35 @@
   scoped_refptr<URLMatcherConditionSet> result;
 
   // {"hostContains": "exaMple"}
-  base::DictionaryValue invalid_condition1;
-  invalid_condition1.SetString(keys::kHostContainsKey, "exaMple");
+  base::Value::Dict invalid_condition1;
+  invalid_condition1.Set(keys::kHostContainsKey, "exaMple");
 
   // {"hostSuffix": ".Com"}
-  base::DictionaryValue invalid_condition2;
-  invalid_condition2.SetString(keys::kHostSuffixKey, ".Com");
+  base::Value::Dict invalid_condition2;
+  invalid_condition2.Set(keys::kHostSuffixKey, ".Com");
 
   // {"hostPrefix": "WWw."}
-  base::DictionaryValue invalid_condition3;
-  invalid_condition3.SetString(keys::kHostPrefixKey, "WWw.");
+  base::Value::Dict invalid_condition3;
+  invalid_condition3.Set(keys::kHostPrefixKey, "WWw.");
 
   // {"hostEquals": "WWW.example.Com"}
-  base::DictionaryValue invalid_condition4;
-  invalid_condition4.SetString(keys::kHostEqualsKey, "WWW.example.Com");
+  base::Value::Dict invalid_condition4;
+  invalid_condition4.Set(keys::kHostEqualsKey, "WWW.example.Com");
 
   // {"scheme": ["HTTP"]}
-  auto scheme_list = std::make_unique<base::ListValue>();
-  scheme_list->Append("HTTP");
-  base::DictionaryValue invalid_condition5;
+  base::Value::List scheme_list;
+  scheme_list.Append("HTTP");
+  base::Value::Dict invalid_condition5;
   invalid_condition5.Set(keys::kSchemesKey, std::move(scheme_list));
 
-  const base::DictionaryValue* invalid_conditions[] = {
-    &invalid_condition1,
-    &invalid_condition2,
-    &invalid_condition3,
-    &invalid_condition4,
-    &invalid_condition5
-  };
+  const base::Value::Dict* invalid_conditions[] = {
+      &invalid_condition1, &invalid_condition2, &invalid_condition3,
+      &invalid_condition4, &invalid_condition5};
 
   for (size_t i = 0; i < std::size(invalid_conditions); ++i) {
     error.clear();
     result = URLMatcherFactory::CreateFromURLFilterDictionary(
-        matcher.condition_factory(), invalid_conditions[i], 1, &error);
+        matcher.condition_factory(), *invalid_conditions[i], 1, &error);
     EXPECT_FALSE(error.empty()) << "in iteration " << i;
     EXPECT_FALSE(result) << "in iteration " << i;
   }
@@ -232,14 +228,14 @@
 void UrlConditionCaseTest::CheckCondition(
     const std::string& value,
     UrlConditionCaseTest::ResultType expected_result) const {
-  base::DictionaryValue condition;
+  base::Value::Dict condition;
   if (use_list_of_strings_) {
     auto list = std::make_unique<base::ListValue>();
     list->Append(value);
-    condition.SetKey(condition_key_,
-                     base::Value::FromUniquePtrValue(std::move(list)));
+    condition.Set(condition_key_,
+                  base::Value::FromUniquePtrValue(std::move(list)));
   } else {
-    condition.SetKey(condition_key_, base::Value(value));
+    condition.Set(condition_key_, base::Value(value));
   }
 
   URLMatcher matcher;
@@ -247,7 +243,7 @@
   scoped_refptr<URLMatcherConditionSet> result;
 
   result = URLMatcherFactory::CreateFromURLFilterDictionary(
-      matcher.condition_factory(), &condition, 1, &error);
+      matcher.condition_factory(), condition, 1, &error);
   if (expected_result == CREATE_FAILURE) {
     EXPECT_FALSE(error.empty());
     EXPECT_FALSE(result);
diff --git a/components/url_pattern_index/url_pattern_index.cc b/components/url_pattern_index/url_pattern_index.cc
index 8911cd6..8546d93 100644
--- a/components/url_pattern_index/url_pattern_index.cc
+++ b/components/url_pattern_index/url_pattern_index.cc
@@ -774,6 +774,13 @@
   return !rule.initiator_domains_included();
 }
 
+// Returns whether the `host` matches the domain conditions. It's considered a
+// match if both:
+//  1. An included domain matches the `host`, or `domains_included` is omitted
+//     entirely (since rules match all domains by default).
+//  2. No excluded domain match the `host`, or the longest matching excluded
+//     domain is shorter than the longest matching included domain (since
+//     longer, more specific domain matches take precedence).
 bool DoesHostMatchDomainLists(
     base::StringPiece host,
     const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>*
diff --git a/components/user_prefs/android/BUILD.gn b/components/user_prefs/android/BUILD.gn
index edc94b4..f0f54f4 100644
--- a/components/user_prefs/android/BUILD.gn
+++ b/components/user_prefs/android/BUILD.gn
@@ -12,6 +12,7 @@
   sources = [ "java/src/org/chromium/components/user_prefs/UserPrefs.java" ]
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/prefs/android:java",
     "//content/public/android:content_full_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn
index aabaa6c..81f2189 100644
--- a/components/variations/BUILD.gn
+++ b/components/variations/BUILD.gn
@@ -208,6 +208,7 @@
     "hashing_unittest.cc",
     "net/variations_command_line_unittest.cc",
     "net/variations_http_headers_unittest.cc",
+    "processed_study_unittest.cc",
     "simulate_for_crosstalk_unittest.cc",
     "study_filtering_unittest.cc",
     "synthetic_trial_registry_unittest.cc",
diff --git a/components/variations/android/BUILD.gn b/components/variations/android/BUILD.gn
index 8eabe97..b1505fd 100644
--- a/components/variations/android/BUILD.gn
+++ b/components/variations/android/BUILD.gn
@@ -7,6 +7,7 @@
 android_library("variations_java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//components/variations:variations_java",
     "//components/variations/proto:proto_java",
     "//net/android:net_java",
diff --git a/components/variations/processed_study.cc b/components/variations/processed_study.cc
index 9aad00b..b3b3136 100644
--- a/components/variations/processed_study.cc
+++ b/components/variations/processed_study.cc
@@ -14,26 +14,8 @@
 #include "components/variations/proto/study.pb.h"
 
 namespace variations {
-
 namespace {
 
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-enum class InvalidStudyReason {
-  kInvalidMinVersion = 0,
-  kInvalidMaxVersion = 1,
-  kInvalidMinOsVersion = 2,
-  kInvalidMaxOsVersion = 3,
-  kMissingExperimentName = 4,
-  kRepeatedExperimentName = 5,
-  kTotalProbabilityOverflow = 6,
-  kMissingDefaultExperimentInList = 7,
-  kBlankStudyName = 8,
-  kExperimentProbabilityOverflow = 9,
-  kTriggerAndNonTriggerExperimentId = 10,
-  kMaxValue = kTriggerAndNonTriggerExperimentId,
-};
-
 void LogInvalidReason(InvalidStudyReason reason) {
   base::UmaHistogramEnumeration("Variations.InvalidStudyReason", reason);
 }
diff --git a/components/variations/processed_study.h b/components/variations/processed_study.h
index 9034012a..ab8e523 100644
--- a/components/variations/processed_study.h
+++ b/components/variations/processed_study.h
@@ -14,6 +14,23 @@
 
 namespace variations {
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused. Exposed for testing.
+enum class InvalidStudyReason {
+  kInvalidMinVersion = 0,
+  kInvalidMaxVersion = 1,
+  kInvalidMinOsVersion = 2,
+  kInvalidMaxOsVersion = 3,
+  kMissingExperimentName = 4,
+  kRepeatedExperimentName = 5,
+  kTotalProbabilityOverflow = 6,
+  kMissingDefaultExperimentInList = 7,
+  kBlankStudyName = 8,
+  kExperimentProbabilityOverflow = 9,
+  kTriggerAndNonTriggerExperimentId = 10,
+  kMaxValue = kTriggerAndNonTriggerExperimentId,
+};
+
 class Study;
 
 // Wrapper over Study with extra information computed during pre-processing,
diff --git a/components/variations/processed_study_unittest.cc b/components/variations/processed_study_unittest.cc
new file mode 100644
index 0000000..3364343
--- /dev/null
+++ b/components/variations/processed_study_unittest.cc
@@ -0,0 +1,241 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/variations/processed_study.h"
+
+#include <cstdint>
+
+#include "base/test/metrics/histogram_tester.h"
+#include "components/variations/proto/study.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace variations {
+namespace {
+
+const char kInvalidStudyReasonHistogram[] = "Variations.InvalidStudyReason";
+const uint32_t kMaxProbabilityValue =
+    std::numeric_limits<base::FieldTrial::Probability>::max();
+
+// Adds an experiment with the given name and probability to a study.
+Study::Experiment* AddExperiment(Study& study,
+                                 const std::string& name,
+                                 uint32_t probability) {
+  Study::Experiment* experiment = study.add_experiment();
+  experiment->set_name(name);
+  experiment->set_probability_weight(probability);
+  return experiment;
+}
+
+// Creates a study with the given name.
+Study CreateStudy(const std::string& name) {
+  Study study;
+  study.set_name(name);
+  return study;
+}
+
+// Creates a valid study named "Study". This study has min and max version
+// filters, min and max OS version filters, and three groups: Default, Enabled,
+// and Disabled. The Enabled and Disabled groups have GWS IDs. The study's
+// default experiment is the Default group.
+Study CreateValidStudy() {
+  Study study = CreateStudy("Study");
+
+  Study::Filter* filter = study.mutable_filter();
+  filter->set_min_version("1.1.*");
+  filter->set_max_version("2.2.2.2");
+  filter->set_min_os_version("1");
+  filter->set_max_os_version("2.*");
+
+  Study::Experiment* default_experiment = AddExperiment(study, "Default", 0);
+
+  Study::Experiment* enabled_experiment = AddExperiment(study, "Enabled", 50);
+  enabled_experiment->set_google_web_experiment_id(1);
+
+  Study::Experiment* disabled_experiment = AddExperiment(study, "Disabled", 50);
+  disabled_experiment->set_google_web_experiment_id(2);
+
+  study.set_default_experiment_name(default_experiment->name());
+
+  return study;
+}
+
+}  // namespace
+
+TEST(ProcessedStudyTest, InitValidStudy) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateValidStudy();
+
+  ProcessedStudy processed_study;
+  EXPECT_TRUE(processed_study.Init(&study, false));
+  histogram_tester.ExpectTotalCount(kInvalidStudyReasonHistogram, 0);
+}
+
+// Verifies that a study with an invalid min version filter is invalid.
+TEST(ProcessedStudyTest, InitInvalidMinVersion) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateValidStudy();
+  study.mutable_filter()->set_min_version("invalid");
+
+  ProcessedStudy processed_study;
+  EXPECT_FALSE(processed_study.Init(&study, false));
+  histogram_tester.ExpectUniqueSample(
+      kInvalidStudyReasonHistogram, InvalidStudyReason::kInvalidMinVersion, 1);
+}
+
+// Verifies that a study with an invalid max version filter is invalid.
+TEST(ProcessedStudyTest, InitInvalidMaxVersion) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateValidStudy();
+  study.mutable_filter()->set_max_version("1.invalid.1");
+
+  ProcessedStudy processed_study;
+  EXPECT_FALSE(processed_study.Init(&study, false));
+  histogram_tester.ExpectUniqueSample(
+      kInvalidStudyReasonHistogram, InvalidStudyReason::kInvalidMaxVersion, 1);
+}
+
+// Verifies that a study with an invalid min OS version filter is invalid.
+TEST(ProcessedStudyTest, InitInvalidMinOsVersion) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateValidStudy();
+  study.mutable_filter()->set_min_os_version("0.*.0");
+
+  ProcessedStudy processed_study;
+  EXPECT_FALSE(processed_study.Init(&study, false));
+  histogram_tester.ExpectUniqueSample(kInvalidStudyReasonHistogram,
+                                      InvalidStudyReason::kInvalidMinOsVersion,
+                                      1);
+}
+
+// Verifies that a study with an invalid max OS version filter is invalid.
+TEST(ProcessedStudyTest, InitInvalidMaxOsVersion) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateValidStudy();
+  study.mutable_filter()->set_max_os_version("\001\000\000\003");
+
+  ProcessedStudy processed_study;
+  EXPECT_FALSE(processed_study.Init(&study, false));
+  histogram_tester.ExpectUniqueSample(kInvalidStudyReasonHistogram,
+                                      InvalidStudyReason::kInvalidMaxOsVersion,
+                                      1);
+}
+
+// Verifies that a study with a blank study name is invalid.
+TEST(ProcessedStudyTest, InitBlankStudyName) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateValidStudy();
+  study.set_name("");
+
+  ProcessedStudy processed_study;
+  EXPECT_FALSE(processed_study.Init(&study, false));
+  histogram_tester.ExpectUniqueSample(kInvalidStudyReasonHistogram,
+                                      InvalidStudyReason::kBlankStudyName, 1);
+}
+
+// Verifies that a study with an experiment that has no name is invalid.
+TEST(ProcessedStudyTest, InitMissingExperimentName) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateValidStudy();
+
+  AddExperiment(study, "", 0);
+
+  ProcessedStudy processed_study;
+  EXPECT_FALSE(processed_study.Init(&study, false));
+  histogram_tester.ExpectUniqueSample(
+      kInvalidStudyReasonHistogram, InvalidStudyReason::kMissingExperimentName,
+      1);
+}
+
+// Verifies that a study with multiple experiments that are named the same is
+// invalid.
+TEST(ProcessedStudyTest, InitRepeatedExperimentName) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateValidStudy();
+
+  AddExperiment(study, "Group", 0);
+  AddExperiment(study, "Group", 0);
+
+  ProcessedStudy processed_study;
+  EXPECT_FALSE(processed_study.Init(&study, false));
+  histogram_tester.ExpectUniqueSample(
+      kInvalidStudyReasonHistogram, InvalidStudyReason::kRepeatedExperimentName,
+      1);
+}
+
+// Verifies that a study with an experiment that specified both a trigger and
+// non-trigger GWS id is invalid.
+TEST(ProcessedStudyTest, InitTriggerAndNonTriggerExperimentId) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateValidStudy();
+
+  Study::Experiment* experiment = AddExperiment(study, "Group", 0);
+  experiment->set_google_web_experiment_id(123);
+  experiment->set_google_web_trigger_experiment_id(123);
+
+  ProcessedStudy processed_study;
+  EXPECT_FALSE(processed_study.Init(&study, false));
+  histogram_tester.ExpectUniqueSample(
+      kInvalidStudyReasonHistogram,
+      InvalidStudyReason::kTriggerAndNonTriggerExperimentId, 1);
+}
+
+// Verifies that a study with an experiment that has a probability over the
+// maximum is invalid.
+TEST(ProcessedStudyTest, InitExperimentProbabilityOverflow) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateStudy("Study");
+
+  AddExperiment(study, "Group", kMaxProbabilityValue + 1);
+
+  ProcessedStudy processed_study;
+  EXPECT_FALSE(processed_study.Init(&study, false));
+  histogram_tester.ExpectUniqueSample(
+      kInvalidStudyReasonHistogram,
+      InvalidStudyReason::kExperimentProbabilityOverflow, 1);
+}
+
+// Verifies that a study with groups whose total probability is over the maximum
+// is invalid.
+TEST(ProcessedStudyTest, InitTotalProbabilityOverflow) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateStudy("Study");
+
+  AddExperiment(study, "Group1", kMaxProbabilityValue);
+  AddExperiment(study, "Group2", 1);
+
+  ProcessedStudy processed_study;
+  EXPECT_FALSE(processed_study.Init(&study, false));
+  histogram_tester.ExpectUniqueSample(
+      kInvalidStudyReasonHistogram,
+      InvalidStudyReason::kTotalProbabilityOverflow, 1);
+}
+
+// Verifies that a study that specifies a default experiment name but does not
+// contain an experiment with that name is invalid.
+TEST(ProcessedStudyTest, InitMissingDefaultExperimentInList) {
+  base::HistogramTester histogram_tester;
+
+  Study study = CreateValidStudy();
+
+  study.set_default_experiment_name("NonExistentGroup");
+
+  ProcessedStudy processed_study;
+  EXPECT_FALSE(processed_study.Init(&study, false));
+  histogram_tester.ExpectUniqueSample(
+      kInvalidStudyReasonHistogram,
+      InvalidStudyReason::kMissingDefaultExperimentInList, 1);
+}
+
+}  // namespace variations
\ No newline at end of file
diff --git a/components/version_info/android/BUILD.gn b/components/version_info/android/BUILD.gn
index b83d435..dd44ead 100644
--- a/components/version_info/android/BUILD.gn
+++ b/components/version_info/android/BUILD.gn
@@ -19,6 +19,7 @@
   deps = [
     ":generate_version_constants",
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
   srcjar_deps = [ ":channel_enum_srcjar" ]
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 7f170ec..c1401f5b 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -458,7 +458,10 @@
 
 if (is_android) {
   android_library("common_java") {
-    deps = [ "//base:base_java" ]
+    deps = [
+      "//base:base_java",
+      "//build/android:build_java",
+    ]
     sources = [
       "java/src/org/chromium/components/viz/common/VizSwitches.java",
       "java/src/org/chromium/components/viz/common/display/DeJellyUtils.java",
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 002b3ddf..ca0ae3d 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -728,6 +728,7 @@
   android_library("service_java") {
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//ui/android:ui_no_recycler_view_java",
     ]
     annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/components/webapk/android/libs/client/BUILD.gn b/components/webapk/android/libs/client/BUILD.gn
index 88e4275e..4a6bb82 100644
--- a/components/webapk/android/libs/client/BUILD.gn
+++ b/components/webapk/android/libs/client/BUILD.gn
@@ -31,6 +31,7 @@
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//components/webapk/android/libs/common:java",
     "//testing/android/junit:junit_test_support",
     "//third_party/android_deps:robolectric_all_java",
diff --git a/components/webapps/browser/android/BUILD.gn b/components/webapps/browser/android/BUILD.gn
index 18d2f18..5639b6d4 100644
--- a/components/webapps/browser/android/BUILD.gn
+++ b/components/webapps/browser/android/BUILD.gn
@@ -34,6 +34,7 @@
   deps = [
     ":java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/browser_ui/bottomsheet/android:java",
     "//components/browser_ui/widget/android:java",
     "//components/infobars/android:java",
diff --git a/components/webauthn/android/BUILD.gn b/components/webauthn/android/BUILD.gn
index 647842c..6fdacf8 100644
--- a/components/webauthn/android/BUILD.gn
+++ b/components/webauthn/android/BUILD.gn
@@ -34,6 +34,7 @@
     "$google_play_services_package:google_play_services_tasks_java",
     "//base:base_java",
     "//base:jni_java",
+    "//build/android:build_java",
     "//components/externalauth/android:java",
     "//components/payments/content/android:feature_list_java",
     "//content/public/android:content_java",
diff --git a/components/webxr/android/BUILD.gn b/components/webxr/android/BUILD.gn
index 003d0fe8..45075e1 100644
--- a/components/webxr/android/BUILD.gn
+++ b/components/webxr/android/BUILD.gn
@@ -75,6 +75,7 @@
     ":ar_java_interfaces",
     ":webxr_android_enums_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
@@ -101,6 +102,7 @@
     ":ar_java_base",
     ":webxr_android_enums_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/arcore-android-sdk-client:com_google_ar_core_java",
   ]
 
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc
index b70a2ac..c44870f1 100644
--- a/content/browser/interest_group/interest_group_browsertest.cc
+++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -2988,8 +2988,10 @@
 // Runs ad auction with fenced frames enabled. The auction should succeed and
 // be loaded in a fenced frames. The displayed ad leaves the interest group
 // from a nested iframe.
+//
+// TODO(crbug.com/1320438): Re-enable the test.
 IN_PROC_BROWSER_TEST_P(InterestGroupFencedFrameBrowserTest,
-                       RunAdAuctionWithWinnerNestedLeaveGroup) {
+                       DISABLED_RunAdAuctionWithWinnerNestedLeaveGroup) {
   URLLoaderMonitor url_loader_monitor;
 
   GURL test_url =
diff --git a/content/browser/renderer_host/frame_tree_browsertest.cc b/content/browser/renderer_host/frame_tree_browsertest.cc
index d378c8d4..a534c30 100644
--- a/content/browser/renderer_host/frame_tree_browsertest.cc
+++ b/content/browser/renderer_host/frame_tree_browsertest.cc
@@ -12,6 +12,7 @@
 #include "content/browser/fenced_frame/fenced_frame_url_mapping.h"
 #include "content/browser/renderer_host/frame_tree.h"
 #include "content/browser/renderer_host/frame_tree_node.h"
+#include "content/browser/renderer_host/navigation_entry_restore_context_impl.h"
 #include "content/browser/renderer_host/navigation_request.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
@@ -23,6 +24,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/origin_util.h"
 #include "content/public/common/url_constants.h"
+#include "content/public/test/back_forward_cache_util.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
@@ -2382,11 +2384,13 @@
   GURL new_main_url(https_server()->GetURL("b.test", "/hello.html"));
   EXPECT_TRUE(NavigateToURL(shell(), new_main_url));
   EXPECT_EQ(2, root->navigator().controller().GetEntryCount());
+  EXPECT_EQ(new_main_url, root->current_frame_host()->GetLastCommittedURL());
 
   // Go back.
   TestNavigationObserver back_load_observer(shell()->web_contents());
   root->navigator().controller().GoBack();
   back_load_observer.Wait();
+  EXPECT_EQ(2, root->navigator().controller().GetEntryCount());
 
   EXPECT_EQ(1U, root->child_count());
   fenced_frame = GetFencedFrameRootNode(root->child_at(0));
@@ -2418,6 +2422,201 @@
   }
 }
 
+// Simulates the crash in crbug.com/1317642 by disabling BFCache and going back
+// to a page with a fenced frame navigation, which in shadowDOM FFs will lead to
+// a AUTO_SUBFRAME navigation initiated in the browser.
+IN_PROC_BROWSER_TEST_P(FencedFrameTreeBrowserTest,
+                       GoBackToPageWithFencedFrameNavigationNoBFCache) {
+  GURL main_url(https_server()->GetURL(
+      "a.test",
+      "/fenced_frames/basic_fenced_frame_src_navigate_on_click.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // It is safe to obtain the root frame tree node here, as it doesn't change.
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetPrimaryFrameTree()
+                            .root();
+
+  EXPECT_EQ(1U, root->child_count());
+  auto* fenced_frame = GetFencedFrameRootNode(root->child_at(0));
+  EXPECT_TRUE(fenced_frame->IsFencedFrameRoot());
+  EXPECT_TRUE(fenced_frame->IsInFencedFrameTree());
+
+  // Since the fenced frame is not yet navigated, it's specific controller
+  // should have an entry count of 0.
+  if (GetParam() == blink::features::FencedFramesImplementationType::kMPArch) {
+    EXPECT_EQ(0, fenced_frame->navigator().controller().GetEntryCount());
+  }
+
+  TestFrameNavigationObserver observer(fenced_frame);
+  EXPECT_TRUE(
+      ExecJs(root, "document.getElementsByTagName('button')[0].click();"));
+  observer.WaitForCommit();
+  GURL fenced_frame_url_1 =
+      https_server()->GetURL("a.test", "/fenced_frames/title1.html");
+
+  // ShadowDOM fenced frames have the same NavigationController as the top-level
+  // frame, therefore checking `root->navigator().controller()` while MPArch
+  // fenced frame has its own NavigationController so checking
+  // `fenced_frame->navigator().controller()`.
+  if (GetParam() ==
+      blink::features::FencedFramesImplementationType::kShadowDOM) {
+    EXPECT_EQ(1, root->navigator().controller().GetEntryCount());
+    EXPECT_EQ(root->navigator().controller().GetEntryCount(),
+              fenced_frame->navigator().controller().GetEntryCount());
+  } else {
+    EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+    EXPECT_EQ(1, fenced_frame->navigator().controller().GetEntryCount());
+  }
+  EXPECT_EQ(fenced_frame_url_1,
+            fenced_frame->current_frame_host()->GetLastCommittedURL());
+  DisableBackForwardCacheForTesting(shell()->web_contents(),
+                                    BackForwardCache::TEST_REQUIRES_NO_CACHING);
+
+  // Navigate the top-level page to another document.
+  GURL new_main_url(https_server()->GetURL("b.test", "/hello.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), new_main_url));
+  EXPECT_EQ(2, root->navigator().controller().GetEntryCount());
+  EXPECT_EQ(new_main_url, root->current_frame_host()->GetLastCommittedURL());
+
+  // Go back.
+  TestNavigationObserver back_load_observer(shell()->web_contents());
+  root->navigator().controller().GoBack();
+  back_load_observer.Wait();
+  EXPECT_EQ(2, root->navigator().controller().GetEntryCount());
+
+  EXPECT_EQ(1U, root->child_count());
+  fenced_frame = GetFencedFrameRootNode(root->child_at(0));
+  EXPECT_TRUE(fenced_frame->IsFencedFrameRoot());
+  EXPECT_TRUE(fenced_frame->IsInFencedFrameTree());
+
+  // ShadowDOM fenced frames have the same NavigationController as the top-level
+  // frame, therefore the count here is 2 because of the navigation of the
+  // top-level frame.
+  // Note the last committed url is the latest one in shadowDOM due to the joint
+  // history maintained in the single navigation controller and going back can
+  // therefore get the latest navigation in the frame which is
+  // `fenced_frame_url_1`.
+  // MPArch fenced frame has its own NavigationController which is not retained
+  // when the top-level page navigates. Therefore going back lands on the
+  // initial fenced frame without any navigation.
+  if (GetParam() ==
+      blink::features::FencedFramesImplementationType::kShadowDOM) {
+    EXPECT_EQ(2, root->navigator().controller().GetEntryCount());
+    EXPECT_EQ(root->navigator().controller().GetEntryCount(),
+              fenced_frame->navigator().controller().GetEntryCount());
+    EXPECT_EQ(fenced_frame_url_1,
+              fenced_frame->current_frame_host()->GetLastCommittedURL());
+  } else {
+    EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+    EXPECT_EQ(0, fenced_frame->navigator().controller().GetEntryCount());
+  }
+}
+
+IN_PROC_BROWSER_TEST_P(FencedFrameTreeBrowserTest,
+                       RestorePageWithFencedFrameNavigation) {
+  GURL main_url(https_server()->GetURL(
+      "a.test",
+      "/fenced_frames/basic_fenced_frame_src_navigate_on_click.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // It is safe to obtain the root frame tree node here, as it doesn't change.
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetPrimaryFrameTree()
+                            .root();
+
+  EXPECT_EQ(1U, root->child_count());
+  auto* fenced_frame = GetFencedFrameRootNode(root->child_at(0));
+  EXPECT_TRUE(fenced_frame->IsFencedFrameRoot());
+  EXPECT_TRUE(fenced_frame->IsInFencedFrameTree());
+
+  TestFrameNavigationObserver observer(fenced_frame);
+  EXPECT_TRUE(
+      ExecJs(root, "document.getElementsByTagName('button')[0].click();"));
+  observer.WaitForCommit();
+  GURL fenced_frame_url_1 =
+      https_server()->GetURL("a.test", "/fenced_frames/title1.html");
+
+  // ShadowDOM fenced frames have the same NavigationController as the top-level
+  // frame, therefore checking `root->navigator().controller()` while MPArch
+  // fenced frame has its own NavigationController so checking
+  // `fenced_frame->navigator().controller()`.
+  if (GetParam() ==
+      blink::features::FencedFramesImplementationType::kShadowDOM) {
+    EXPECT_EQ(1, root->navigator().controller().GetEntryCount());
+    EXPECT_EQ(root->navigator().controller().GetEntryCount(),
+              fenced_frame->navigator().controller().GetEntryCount());
+  } else {
+    EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+    EXPECT_EQ(1, fenced_frame->navigator().controller().GetEntryCount());
+  }
+  EXPECT_EQ(fenced_frame_url_1,
+            fenced_frame->current_frame_host()->GetLastCommittedURL());
+
+  NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
+      shell()->web_contents()->GetController());
+  std::unique_ptr<NavigationEntryImpl> restored_entry =
+      NavigationEntryImpl::FromNavigationEntry(
+          NavigationController::CreateNavigationEntry(
+              main_url, Referrer(), absl::nullopt, ui::PAGE_TRANSITION_RELOAD,
+              false, std::string(), controller.GetBrowserContext(),
+              nullptr /* blob_url_loader_factory */));
+  std::unique_ptr<NavigationEntryRestoreContextImpl> context =
+      std::make_unique<NavigationEntryRestoreContextImpl>();
+  restored_entry->SetPageState(blink::PageState::CreateFromURL(main_url),
+                               context.get());
+  EXPECT_EQ(0U, restored_entry->root_node()->children.size());
+
+  // Restore the new entry in a new tab and verify the fenced frame loads.
+  std::vector<std::unique_ptr<NavigationEntry>> entries;
+  entries.push_back(std::move(restored_entry));
+
+  Shell* new_shell = Shell::CreateNewWindow(
+      controller.GetBrowserContext(), GURL::EmptyGURL(), nullptr, gfx::Size());
+  FrameTreeNode* new_root =
+      static_cast<WebContentsImpl*>(new_shell->web_contents())
+          ->GetPrimaryFrameTree()
+          .root();
+  NavigationControllerImpl& new_controller =
+      static_cast<NavigationControllerImpl&>(
+          new_shell->web_contents()->GetController());
+  new_controller.Restore(entries.size() - 1, RestoreType::kRestored, &entries);
+
+  ASSERT_EQ(0u, entries.size());
+  {
+    TestNavigationObserver restore_observer(new_shell->web_contents());
+    new_controller.LoadIfNecessary();
+    restore_observer.Wait();
+  }
+  ASSERT_EQ(1U, new_root->child_count());
+  EXPECT_EQ(main_url, new_root->current_url());
+
+  auto* restored_fenced_frame = GetFencedFrameRootNode(new_root->child_at(0));
+  EXPECT_TRUE(restored_fenced_frame->IsFencedFrameRoot());
+  EXPECT_TRUE(restored_fenced_frame->IsInFencedFrameTree());
+
+  EXPECT_EQ(1, new_controller.GetEntryCount());
+  EXPECT_EQ(0, new_controller.GetLastCommittedEntryIndex());
+  NavigationEntryImpl* new_entry = controller.GetLastCommittedEntry();
+  EXPECT_EQ(main_url, new_entry->root_node()->frame_entry->url());
+
+  if (GetParam() ==
+      blink::features::FencedFramesImplementationType::kShadowDOM) {
+    // ShadowDOM FF gets restored as it is part of the restored NavigationEntry
+    // from the primary FrameTree's NavigationController
+    ASSERT_EQ(1U, new_entry->root_node()->children.size());
+    EXPECT_EQ(fenced_frame_url_1,
+              new_entry->root_node()->children[0]->frame_entry->url());
+  } else {
+    // MPArch navigation controller wouldn't have any entry since it's not
+    // restored. Therefore we will only have the initial fenced frame without
+    // any navigation.
+    ASSERT_EQ(0U, new_entry->root_node()->children.size());
+    EXPECT_EQ(0,
+              restored_fenced_frame->navigator().controller().GetEntryCount());
+  }
+}
+
 IN_PROC_BROWSER_TEST_P(FencedFrameTreeBrowserTest, CheckInvalidUrnError) {
   GURL main_url = https_server()->GetURL("b.test", "/hello.html");
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 85489a9..4a4cd9cc 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -1208,16 +1208,6 @@
   // RenderFrameHostImpl::ValidateDidCommitParams. By the time we get here, some
   // effects of the navigation have already occurred.
 
-  if (ShouldMaintainTrivialSessionHistory(rfh->frame_tree_node()) &&
-      GetLastCommittedEntry()) {
-    // Ensure that this navigation does not add a navigation entry, since
-    // ShouldMaintainTrivialSessionHistory() means we should not add an entry
-    // beyond the last committed one. Therefore, `should_replace_current_entry`
-    // should be set, which replaces the current entry, or this should be a
-    // reload, which does not create a new entry.
-    DCHECK(params.should_replace_current_entry ||
-           navigation_request->GetReloadType() != ReloadType::NONE);
-  }
   is_initial_navigation_ = false;
 
   // Save the previous state before we clobber it.
@@ -1340,6 +1330,24 @@
 
   // Do navigation-type specific actions. These will make and commit an entry.
   details->type = ClassifyNavigation(rfh, params, navigation_request);
+
+  if (ShouldMaintainTrivialSessionHistory(rfh->frame_tree_node()) &&
+      GetLastCommittedEntry()) {
+    // Ensure that this navigation does not add a navigation entry, since
+    // ShouldMaintainTrivialSessionHistory() means we should not add an entry
+    // beyond the last committed one. Therefore, `should_replace_current_entry`
+    // should be set, which replaces the current entry, or this should be a
+    // reload, which does not create a new entry.
+    // In shadowDOM fenced frames, on a history/tab-restore navigation, any
+    // navigation that is restored will not be creating a new entry anyways, so
+    // exclude that case by checking NAVIGATION_TYPE_AUTO_SUBFRAME.
+    // TODO(crbug.com/1319919): Consider adjusting the dcheck for more cases as
+    // pointed out in the issue.
+    DCHECK(params.should_replace_current_entry ||
+           navigation_request->GetReloadType() != ReloadType::NONE ||
+           details->type == NAVIGATION_TYPE_AUTO_SUBFRAME);
+  }
+
   if (GetLastCommittedEntry() && GetLastCommittedEntry()->IsInitialEntry()) {
     if (rfh->GetParent()) {
       // This is a subframe navigation on the initial empty document, which used
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index add6707..87cd900 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -2588,6 +2588,42 @@
           .ExtractBool());
 }
 
+// Test to make sure that an iframe with a data:url is process isolated.
+IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
+                       SandboxedIframeWithDataURLIsIsolated) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // 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(ExecJs(shell(), js_str));
+    ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+  }
+
+  // Verify parent and child frames don't share a SiteInstance
+  FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
+  ASSERT_EQ(1U, root->child_count());
+  FrameTreeNode* child = root->child_at(0);
+  EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+            child->current_frame_host()->GetSiteInstance());
+  EXPECT_TRUE(child->current_frame_host()
+                  ->GetSiteInstance()
+                  ->GetSiteInfo()
+                  .is_sandboxed());
+  EXPECT_FALSE(root->current_frame_host()
+                   ->GetSiteInstance()
+                   ->GetSiteInfo()
+                   .is_sandboxed());
+}
+
 // Test to make sure that an iframe with a data:url is appropriately sandboxed.
 IN_PROC_BROWSER_TEST_P(SitePerProcessIsolatedSandboxedIframeTest,
                        SandboxedIframeWithDataURL) {
diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc
index 8a5b3cd..a175906 100644
--- a/content/browser/webauth/authenticator_common.cc
+++ b/content/browser/webauth/authenticator_common.cc
@@ -485,17 +485,7 @@
           BackForwardCacheDisable::DisabledReasonId::kWebAuthenticationAPI));
 }
 
-AuthenticatorCommon::~AuthenticatorCommon() {
-  // Resolve pending callbacks before disconnecting the receiver.
-  if (make_credential_response_callback_) {
-    CompleteMakeCredentialRequest(
-        blink::mojom::AuthenticatorStatus::UNKNOWN_ERROR);
-  }
-  if (get_assertion_response_callback_) {
-    CompleteGetAssertionRequest(
-        blink::mojom::AuthenticatorStatus::UNKNOWN_ERROR);
-  }
-}
+AuthenticatorCommon::~AuthenticatorCommon() = default;
 
 std::unique_ptr<AuthenticatorRequestClientDelegate>
 AuthenticatorCommon::MaybeCreateRequestDelegate() {
diff --git a/content/browser/webauth/authenticator_common.h b/content/browser/webauth/authenticator_common.h
index 9505759..8ba756a3 100644
--- a/content/browser/webauth/authenticator_common.h
+++ b/content/browser/webauth/authenticator_common.h
@@ -222,7 +222,7 @@
       device::AuthenticatorGetAssertionResponse response_data,
       absl::optional<std::vector<uint8_t>> large_blob = absl::nullopt);
 
-  // Runs |get_assertion_callback_| and then Cleanup().
+  // Runs |get_assertion_response_callback_| and then Cleanup().
   void CompleteGetAssertionRequest(
       blink::mojom::AuthenticatorStatus status,
       blink::mojom::GetAssertionAuthenticatorResponsePtr response = nullptr,
diff --git a/content/browser/webauth/authenticator_impl.cc b/content/browser/webauth/authenticator_impl.cc
index bdec9d8..b6b86c0 100644
--- a/content/browser/webauth/authenticator_impl.cc
+++ b/content/browser/webauth/authenticator_impl.cc
@@ -42,22 +42,6 @@
 
 AuthenticatorImpl::~AuthenticatorImpl() = default;
 
-// DocumentService
-void AuthenticatorImpl::WillBeDestroyed(DocumentServiceDestructionReason) {
-  // Explicit reset() `authenticator_commmon_` now, which tries to reply to
-  // pending Mojo callbacks in its destructor.
-  //
-  // TODO(https://crbug.com/1317534): Previously, running the callbacks in the
-  // destructor was required to avoid triggering DCHECKs since the
-  // mojo::Receiver was (incorrectly) not yet reset in the destructor.
-  //
-  // The destruction order is fixed so running the reply callbacks should no
-  // longer be necessary; however, there are now unit test-only dependencies on
-  // this behavior. Remove those test dependencies and this `WillBeDestroyed()`
-  // override can be completely deleted.
-  authenticator_common_.reset();
-}
-
 // mojom::Authenticator
 void AuthenticatorImpl::MakeCredential(
     blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
diff --git a/content/browser/webauth/authenticator_impl.h b/content/browser/webauth/authenticator_impl.h
index d0ad078..fe6e5b9d 100644
--- a/content/browser/webauth/authenticator_impl.h
+++ b/content/browser/webauth/authenticator_impl.h
@@ -44,9 +44,6 @@
     return authenticator_common_.get();
   }
 
-  // DocumentService
-  void WillBeDestroyed(DocumentServiceDestructionReason) override;
-
   // mojom:Authenticator
   void MakeCredential(
       blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
diff --git a/content/browser/webauth/webauth_browsertest.cc b/content/browser/webauth/webauth_browsertest.cc
index b6d15ee..26c1cc4 100644
--- a/content/browser/webauth/webauth_browsertest.cc
+++ b/content/browser/webauth/webauth_browsertest.cc
@@ -633,7 +633,6 @@
   EXPECT_TRUE(
       NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html")));
   WaitForConnectionError();
-  create_callback_receiver.WaitForCallback();
 
   // The next active document should be able to successfully call
   // navigator.credentials.create({publicKey: ...}) again.
@@ -663,7 +662,6 @@
   EXPECT_TRUE(
       NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html")));
   WaitForConnectionError();
-  get_callback_receiver.WaitForCallback();
 
   // The next active document should be able to successfully call
   // navigator.credentials.get({publicKey: ...}) again.
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index 6765f6c..ef75031 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -82,6 +82,7 @@
   deps = [
     ":content_java_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/version_info/android:version_constants_java",
     "//third_party/android_deps:com_google_code_findbugs_jsr305_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
@@ -141,6 +142,7 @@
     "$google_play_services_package:google_play_services_tasks_java",
     "//base:base_java",
     "//build:chromeos_buildflags",
+    "//build/android:build_java",
     "//components/download/public/common:public_java",
     "//components/payments/mojom:mojom_java",
     "//content/public/common:trust_tokens_mojo_bindings_java",
@@ -640,6 +642,7 @@
     "//base:base_java_process_launcher_test_support",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//content/public/test/android:content_java_test_support",
     "//media/mojo/mojom:mojom_java",
     "//mojo/public/java:base_java",
diff --git a/content/public/test/android/BUILD.gn b/content/public/test/android/BUILD.gn
index 3736f314..f3e1bd6 100644
--- a/content/public/test/android/BUILD.gn
+++ b/content/public/test/android/BUILD.gn
@@ -11,6 +11,7 @@
   deps = [
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
   ]
   sources = [ "javatests/src/org/chromium/content_public/browser/test/NestedSystemMessageHandler.java" ]
 }
@@ -21,6 +22,7 @@
     ":android_test_message_pump_support_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//mojo/public/java:bindings_java",
     "//net/android:net_java",
diff --git a/content/shell/android/BUILD.gn b/content/shell/android/BUILD.gn
index 3f92028..b7622bf 100644
--- a/content/shell/android/BUILD.gn
+++ b/content/shell/android/BUILD.gn
@@ -82,6 +82,7 @@
     ":content_shell_java_resources",
     ":content_shell_manifest",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/download/internal/common:internal_java",
     "//components/embedder_support/android:content_view_java",
     "//components/embedder_support/android:view_java",
@@ -139,6 +140,7 @@
     ":content_shell_java",
     ":content_shell_manifest",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/embedder_support/android:view_java",
     "//content/public/android:content_java",
     "//media/capture/video/android:capture_java",
@@ -194,6 +196,7 @@
       ":content_shell_java",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//components/crash/android:java",
       "//components/crash/core/app:chrome_crashpad_handler_named_as_so",
       "//content/public/android:content_java",
@@ -248,6 +251,7 @@
     ":content_shell_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//content/public/test/android:content_java_test_support",
     "//content/shell/android:content_shell_java",
@@ -273,6 +277,7 @@
   deps = [
     ":content_shell_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//testing/android/native_test:native_test_java",
     "//third_party/androidx:androidx_core_core_java",
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 6b6dd34..d4ece59 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1071,6 +1071,7 @@
       ":content_browsertests_resources",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//components/download/internal/common:internal_java",
       "//components/viz/service:service_java",
       "//content/public/android:content_java",
@@ -2970,6 +2971,7 @@
       "$google_play_services_package:google_play_services_basement_java",
       "$google_play_services_package:google_play_services_tasks_java",
       "//base:base_java",
+      "//build/android:build_java",
       "//content/public/android:content_java",
       "//ui/android:ui_full_java",
     ]
diff --git a/content/test/attribution_simulator_impl.cc b/content/test/attribution_simulator_impl.cc
index 705c42b..04d1402f 100644
--- a/content/test/attribution_simulator_impl.cc
+++ b/content/test/attribution_simulator_impl.cc
@@ -79,7 +79,6 @@
   return absl::visit(Visitor{}, event.first);
 }
 
-// TODO(apaseltiner): Consider exposing other behaviors here.
 class AlwaysSetCookieChecker : public AttributionCookieChecker {
  public:
   AlwaysSetCookieChecker() = default;
diff --git a/content/test/data/fenced_frames/basic_fenced_frame_src_navigate_on_click.html b/content/test/data/fenced_frames/basic_fenced_frame_src_navigate_on_click.html
new file mode 100644
index 0000000..3f67d67
--- /dev/null
+++ b/content/test/data/fenced_frames/basic_fenced_frame_src_navigate_on_click.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+  <body>
+  <div>
+    <button onclick="navigateFrames();">Navigate</button>
+  </div>
+  <fencedframe mode=opaque-ads id="frame1"></fencedframe>
+
+  <script>
+    function navigateFrames() {
+      document.getElementById('frame1').src="title1.html";
+    }
+  </script>
+
+</body>
+
+</html>
diff --git a/device/BUILD.gn b/device/BUILD.gn
index 90a1f21de..5a27dd8 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -437,6 +437,7 @@
     sources = bluetooth_java_sources_needing_jni
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//components/location/android:location_java",
       "//device/bluetooth:java",
       "//third_party/android_sdk:android_test_mock_java",
@@ -458,6 +459,7 @@
       "//base:base_java",
       "//base:base_java_test_support",
       "//base:base_junit_test_support",
+      "//build/android:build_java",
       "//device/gamepad:java",
       "//mojo/public/java:bindings_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn
index eb4048a..0e85a06 100644
--- a/device/bluetooth/BUILD.gn
+++ b/device/bluetooth/BUILD.gn
@@ -622,6 +622,7 @@
     sources = java_sources_needing_jni
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//components/location/android:location_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
     ]
diff --git a/device/bluetooth/bluetooth_adapter.cc b/device/bluetooth/bluetooth_adapter.cc
index ebac177..e69c618 100644
--- a/device/bluetooth/bluetooth_adapter.cc
+++ b/device/bluetooth/bluetooth_adapter.cc
@@ -473,14 +473,14 @@
     observer.GattDescriptorValueChanged(this, descriptor, value);
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothAdapter::
     NotifyLowEnergyScanSessionHardwareOffloadingStatusChanged(
         LowEnergyScanSessionHardwareOffloadingStatus status) {
   for (auto& observer : observers_)
     observer.LowEnergyScanSessionHardwareOffloadingStatusChanged(status);
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 BluetoothAdapter::SetPoweredCallbacks::SetPoweredCallbacks() = default;
 BluetoothAdapter::SetPoweredCallbacks::~SetPoweredCallbacks() = default;
diff --git a/device/bluetooth/bluetooth_adapter.h b/device/bluetooth/bluetooth_adapter.h
index ca22dfb..5cce1a3 100644
--- a/device/bluetooth/bluetooth_adapter.h
+++ b/device/bluetooth/bluetooth_adapter.h
@@ -29,9 +29,9 @@
 #include "device/bluetooth/bluetooth_export.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "device/bluetooth/bluetooth_low_energy_scan_session.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -43,9 +43,9 @@
 class BluetoothDiscoveryFilter;
 class BluetoothDiscoverySession;
 class BluetoothLocalGattService;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 class BluetoothLowEnergyScanFilter;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 class BluetoothRemoteGattCharacteristic;
 class BluetoothRemoteGattDescriptor;
 class BluetoothRemoteGattService;
@@ -62,13 +62,13 @@
 class DEVICE_BLUETOOTH_EXPORT BluetoothAdapter
     : public base::RefCounted<BluetoothAdapter> {
  public:
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   enum class LowEnergyScanSessionHardwareOffloadingStatus {
     kUndetermined = 0,
     kNotSupported,
     kSupported
   };
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Interface for observing changes from bluetooth adapters.
   class DEVICE_BLUETOOTH_EXPORT Observer {
@@ -328,12 +328,12 @@
         BluetoothRemoteGattDescriptor* descriptor,
         const std::vector<uint8_t>& value) {}
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
     // Called when the low energy scanning hardware offloading support state
     // changes.
     virtual void LowEnergyScanSessionHardwareOffloadingStatusChanged(
         LowEnergyScanSessionHardwareOffloadingStatus status) {}
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
   };
 
   // Used to configure a listening service.
@@ -692,7 +692,7 @@
       BluetoothRemoteGattDescriptor* descriptor,
       const std::vector<uint8_t>& value);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void NotifyLowEnergyScanSessionHardwareOffloadingStatusChanged(
       LowEnergyScanSessionHardwareOffloadingStatus status);
 
@@ -741,7 +741,7 @@
   StartLowEnergyScanSession(
       std::unique_ptr<BluetoothLowEnergyScanFilter> filter,
       base::WeakPtr<BluetoothLowEnergyScanSession::Delegate> delegate) = 0;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Set the adapter name to one chosen from the system information. Only Ash
diff --git a/device/bluetooth/bluetooth_adapter_factory.cc b/device/bluetooth/bluetooth_adapter_factory.cc
index 3526f17..101a668f 100644
--- a/device/bluetooth/bluetooth_adapter_factory.cc
+++ b/device/bluetooth/bluetooth_adapter_factory.cc
@@ -14,7 +14,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/no_destructor.h"
 #include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 
 #if BUILDFLAG(IS_MAC)
@@ -148,7 +147,7 @@
   return Get()->adapter_ != nullptr;
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 // static
 void BluetoothAdapterFactory::SetBleScanParserCallback(
     BleScanParserCallback callback) {
@@ -160,7 +159,7 @@
 BluetoothAdapterFactory::GetBleScanParserCallback() {
   return Get()->ble_scan_parser_;
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 BluetoothAdapterFactory::GlobalValuesForTesting::GlobalValuesForTesting() =
     default;
diff --git a/device/bluetooth/bluetooth_adapter_factory.h b/device/bluetooth/bluetooth_adapter_factory.h
index e4d758f..cdcccb3 100644
--- a/device/bluetooth/bluetooth_adapter_factory.h
+++ b/device/bluetooth/bluetooth_adapter_factory.h
@@ -9,14 +9,13 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_export.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/data_decoder/public/mojom/ble_scan_parser.mojom-forward.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 namespace device {
 
@@ -35,10 +34,10 @@
   using AdapterCallback =
       base::OnceCallback<void(scoped_refptr<BluetoothAdapter> adapter)>;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   using BleScanParserCallback = base::RepeatingCallback<
       mojo::PendingRemote<data_decoder::mojom::BleScanParser>()>;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   BluetoothAdapterFactory();
   ~BluetoothAdapterFactory();
@@ -86,13 +85,13 @@
   // adapter. Exposed for testing.
   static bool HasSharedInstanceForTesting();
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   // Sets the mojo::Remote<BleScanParser> callback used in Get*() below.
   static void SetBleScanParserCallback(BleScanParserCallback callback);
   // Returns a reference to a parser for BLE advertisement packets.
   // This will be an empty callback until something calls Set*() above.
   static BleScanParserCallback GetBleScanParserCallback();
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // ValuestForTesting holds the return values for BluetoothAdapterFactory's
   // functions that have been set for testing.
@@ -159,9 +158,9 @@
   base::WeakPtr<BluetoothAdapter> classic_adapter_;
 #endif
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   BleScanParserCallback ble_scan_parser_;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 };
 
 }  // namespace device
diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc
index cfd96a7..04107af 100644
--- a/device/bluetooth/bluetooth_adapter_unittest.cc
+++ b/device/bluetooth/bluetooth_adapter_unittest.cc
@@ -48,10 +48,10 @@
 #include "device/bluetooth/test/bluetooth_test_fuchsia.h"
 #endif
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "device/bluetooth/bluetooth_low_energy_scan_filter.h"
 #include "device/bluetooth/bluetooth_low_energy_scan_session.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 using device::BluetoothDevice;
 
@@ -138,7 +138,7 @@
     return nullptr;
   }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void SetServiceAllowList(const UUIDList& uuids,
                            base::OnceClosure callback,
                            ErrorCallback error_callback) override {}
@@ -154,7 +154,7 @@
       override {
     return nullptr;
   }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   void SetStandardChromeOSAdapterName() override {}
diff --git a/device/bluetooth/bluetooth_device.h b/device/bluetooth/bluetooth_device.h
index 7becee8..3f91bbf 100644
--- a/device/bluetooth/bluetooth_device.h
+++ b/device/bluetooth/bluetooth_device.h
@@ -23,7 +23,6 @@
 #include "base/strings/string_piece_forward.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/bluetooth_common.h"
 #include "device/bluetooth/bluetooth_export.h"
 #include "device/bluetooth/bluetooth_remote_gatt_service.h"
@@ -657,7 +656,7 @@
   std::vector<BluetoothRemoteGattService*> GetPrimaryServicesByUUID(
       const BluetoothUUID& service_uuid);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   using ExecuteWriteErrorCallback =
       base::OnceCallback<void(device::BluetoothGattService::GattErrorCode)>;
   using AbortWriteErrorCallback =
@@ -668,7 +667,7 @@
   // Aborts all the previous prepare writes in a reliable write session.
   virtual void AbortWrite(base::OnceClosure callback,
                           AbortWriteErrorCallback error_callback) = 0;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
   // Set the battery information for the battery type |info.type|. Overrides
diff --git a/device/bluetooth/bluetooth_device_unittest.cc b/device/bluetooth/bluetooth_device_unittest.cc
index 3066748..17edba5 100644
--- a/device/bluetooth/bluetooth_device_unittest.cc
+++ b/device/bluetooth/bluetooth_device_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/test/bind.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/bluetooth_remote_gatt_service.h"
 #include "device/bluetooth/public/cpp/bluetooth_address.h"
 #include "device/bluetooth/test/mock_pairing_delegate.h"
@@ -1193,9 +1192,9 @@
 // and is non trivial to implement. On ChromeOS, it is not essential for
 // this test to operate, and so it is simply skipped. Android at least
 // does require this step.
-#if !(BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS))
+#if !BUILDFLAG(IS_CHROMEOS)
   StartLowEnergyDiscoverySession();
-#endif  // !(BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS))
+#endif  // !BUILDFLAG(IS_CHROMEOS)
 
   BluetoothDevice* device = SimulateLowEnergyDevice(5);
   EXPECT_FALSE(device->GetName());
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
index 0c3d7e9..c486794 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
@@ -13,7 +13,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/bluetooth_gatt_notify_session.h"
 #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h"
 
@@ -115,7 +114,7 @@
                              std::move(error_callback));
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothRemoteGattCharacteristic::StartNotifySession(
     NotificationType notification_type,
     NotifySessionCallback callback,
@@ -123,7 +122,7 @@
   StartNotifySessionInternal(notification_type, std::move(callback),
                              std::move(error_callback));
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 bool BluetoothRemoteGattCharacteristic::AddDescriptor(
     std::unique_ptr<BluetoothRemoteGattDescriptor> descriptor) {
@@ -240,11 +239,11 @@
   // do whatever else is needed to get the notifications flowing.
   SubscribeToNotifications(
       ccc_descriptor[0],
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
       notification_type.value_or((GetProperties() & PROPERTY_NOTIFY)
                                      ? NotificationType::kNotification
                                      : NotificationType::kIndication),
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
       base::BindOnce(
           &BluetoothRemoteGattCharacteristic::OnStartNotifySessionSuccess,
           GetWeakPtr(), std::move(callback)),
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic.h b/device/bluetooth/bluetooth_remote_gatt_characteristic.h
index 86bfc68..164e32e 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic.h
@@ -18,7 +18,6 @@
 #include "base/containers/queue.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/bluetooth_export.h"
 #include "device/bluetooth/bluetooth_gatt_characteristic.h"
 #include "device/bluetooth/bluetooth_remote_gatt_service.h"
@@ -134,7 +133,7 @@
   // BluetoothGattNotifySession object that you received in |callback|.
   virtual void StartNotifySession(NotifySessionCallback callback,
                                   ErrorCallback error_callback);
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   // TODO(https://crbug.com/849359): This method should also be implemented on
   // Android and Windows.
   // macOS does not support specifying a notification type. According to macOS
@@ -144,7 +143,7 @@
   virtual void StartNotifySession(NotificationType notification_type,
                                   NotifySessionCallback callback,
                                   ErrorCallback error_callback);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Sends a read request to a remote characteristic to read its value.
   // |callback| is called to return the read value or error.
@@ -170,7 +169,7 @@
       base::OnceClosure callback,
       ErrorCallback error_callback) = 0;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   // Sends a prepare write request to a remote characteristic with the value
   // |value|. |callback| is called to signal success and |error_callback| for
   // failures. This method only applies to remote characteristics and will fail
@@ -181,7 +180,7 @@
       const std::vector<uint8_t>& value,
       base::OnceClosure callback,
       ErrorCallback error_callback) = 0;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
  protected:
   using DescriptorMap =
@@ -194,7 +193,7 @@
   // notifications/indications. This method is meant to be called from
   // StartNotifySession and should contain only the code necessary to start
   // listening to characteristic notifications on a particular platform.
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   // |notification_type| specifies the type of notifications that will be
   // enabled: notifications or indications.
   // TODO(https://crbug.com/849359): This method should also be implemented on
@@ -209,7 +208,7 @@
       BluetoothRemoteGattDescriptor* ccc_descriptor,
       base::OnceClosure callback,
       ErrorCallback error_callback) = 0;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Writes to the Client Characteristic Configuration descriptor to disable
   // notifications/indications. This method is meant to be called from
diff --git a/device/bluetooth/bluez/bluetooth_adapter_bluez.cc b/device/bluetooth/bluez/bluetooth_adapter_bluez.cc
index 3a5e2da..267c079 100644
--- a/device/bluetooth/bluez/bluetooth_adapter_bluez.cc
+++ b/device/bluetooth/bluez/bluetooth_adapter_bluez.cc
@@ -55,7 +55,7 @@
 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "base/unguessable_token.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 #include "device/bluetooth/bluez/bluetooth_low_energy_scan_session_bluez.h"
@@ -64,7 +64,7 @@
 #include "device/bluetooth/dbus/bluetooth_advertisement_monitor_application_service_provider.h"
 #include "device/bluetooth/dbus/bluetooth_advertisement_monitor_manager_client.h"
 #include "device/bluetooth/dbus/bluetooth_advertisement_monitor_service_provider.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/constants/devicetype.h"
@@ -89,12 +89,12 @@
 
 const char kDeviceNameArcTouch[] = "Arc Touch BT Mouse";
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 // This root path identifies the application registering low energy scanners
 // through D-Bus.
 constexpr char kAdvertisementMonitorApplicationObjectPath[] =
     "/org/chromium/bluetooth_advertisement_monitor";
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 void OnUnregisterAgentError(const std::string& error_name,
                             const std::string& error_message) {
@@ -126,7 +126,7 @@
   }
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 device::BluetoothDevice::ServiceDataMap ConvertServiceDataMap(
     const base::flat_map<std::string, std::vector<uint8_t>>& input) {
   device::BluetoothDevice::ServiceDataMap output;
@@ -142,7 +142,7 @@
   return device::BluetoothDevice::ManufacturerDataMap(input.begin(),
                                                       input.end());
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 bool IsBatteryDisplayBlocklisted(const BluetoothDevice* device) {
   if (!device->GetName())
@@ -204,7 +204,7 @@
       .Run(device::BluetoothAdvertisement::ErrorCode::ERROR_RESET_ADVERTISING);
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void SetServiceAllowListErrorCallback(
     BluetoothAdapterBlueZ::ErrorCallback error_callback,
     const std::string& error_name,
@@ -214,7 +214,7 @@
                        << error_name << ", error_message = " << error_message;
   std::move(error_callback).Run();
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 }  // namespace
 
@@ -258,9 +258,9 @@
   if (IsPresent())
     RemoveAdapter();  // Also deletes devices_.
   DCHECK(devices_.empty());
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   is_advertisement_monitor_application_provider_registered_ = false;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // profiles_ must be empty because all BluetoothSockets have been notified
   // that this adapter is disappearing.
@@ -299,11 +299,11 @@
   bluez::BluezDBusManager::Get()
       ->GetBluetoothAgentManagerClient()
       ->RemoveObserver(this);
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   bluez::BluezDBusManager::Get()
       ->GetBluetoothAdvertisementMonitorManagerClient()
       ->RemoveObserver(this);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   BLUETOOTH_LOG(EVENT) << "Unregistering pairing agent";
   bluez::BluezDBusManager::Get()
@@ -343,11 +343,11 @@
   bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->AddObserver(this);
   bluez::BluezDBusManager::Get()->GetBluetoothAgentManagerClient()->AddObserver(
       this);
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   bluez::BluezDBusManager::Get()
       ->GetBluetoothAdvertisementMonitorManagerClient()
       ->AddObserver(this);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Register the pairing agent.
   dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus();
@@ -355,14 +355,14 @@
       system_bus, dbus::ObjectPath(kAgentPath), this));
   DCHECK(agent_.get());
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   if (chromeos::features::IsBluetoothAdvertisementMonitoringEnabled()) {
     advertisement_monitor_application_provider_ =
         BluetoothAdvertisementMonitorApplicationServiceProvider::Create(
             system_bus,
             dbus::ObjectPath(kAdvertisementMonitorApplicationObjectPath));
   }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   std::vector<dbus::ObjectPath> object_paths = bluez::BluezDBusManager::Get()
                                                    ->GetBluetoothAdapterClient()
@@ -372,9 +372,9 @@
   if (!object_paths.empty()) {
     BLUETOOTH_LOG(EVENT) << "BlueZ Adapters available: " << object_paths.size();
     SetAdapter(object_paths[0]);
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
     RegisterAdvertisementMonitorApplicationServiceProvider();
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
   }
   initialized_ = true;
   std::move(init_callback_).Run();
@@ -719,9 +719,9 @@
   if (!IsPresent())
     SetAdapter(object_path);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   RegisterAdvertisementMonitorApplicationServiceProvider();
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 }
 
 void BluetoothAdapterBlueZ::AdapterRemoved(
@@ -977,12 +977,12 @@
 void BluetoothAdapterBlueZ::AgentManagerRemoved(
     const dbus::ObjectPath& object_path) {}
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothAdapterBlueZ::SupportedAdvertisementMonitorFeaturesChanged() {
   NotifyLowEnergyScanSessionHardwareOffloadingStatusChanged(
       GetLowEnergyScanSessionHardwareOffloadingStatus());
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 void BluetoothAdapterBlueZ::Released() {
   BLUETOOTH_LOG(EVENT) << "Released";
@@ -1300,9 +1300,9 @@
 
   PresentChanged(false);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   is_advertisement_monitor_application_provider_registered_ = false;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 }
 
 void BluetoothAdapterBlueZ::DiscoverableChanged(bool discoverable) {
@@ -1354,7 +1354,7 @@
   for (auto& observer : observers_)
     observer.DeviceAdvertisementReceived(this, device, rssi, eir);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   if (ble_scan_parser_.is_bound()) {
     ScanRecordCallback callback =
         base::BindOnce(&BluetoothAdapterBlueZ::OnAdvertisementReceived,
@@ -1363,10 +1363,10 @@
                        rssi, device->GetAppearance(), device->object_path());
     ble_scan_parser_->Parse(eir, std::move(callback));
   }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothAdapterBlueZ::OnAdvertisementReceived(
     std::string device_address,
     std::string device_name,
@@ -1396,7 +1396,7 @@
 
   device->SetAdvertisedUUIDs(scan_record->service_uuids);
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 void BluetoothAdapterBlueZ::NotifyDeviceConnectedStateChanged(
     BluetoothDeviceBlueZ* device,
@@ -1404,14 +1404,14 @@
   DCHECK_EQ(device->adapter_, this);
   DCHECK_EQ(device->IsConnected(), is_now_connected);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   if (is_now_connected) {
     device::BluetoothConnectionLogger::RecordDeviceConnected(
         device->GetIdentifier(), device->GetDeviceType());
   } else {
     device::RecordDeviceDisconnect(device->GetDeviceType());
   }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   BluetoothAdapter::NotifyDeviceConnectedStateChanged(device, is_now_connected);
 }
@@ -1575,7 +1575,7 @@
   return true;
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothAdapterBlueZ::SetServiceAllowList(const UUIDList& uuids,
                                                 base::OnceClosure callback,
                                                 ErrorCallback error_callback) {
@@ -1658,7 +1658,7 @@
              ? LowEnergyScanSessionHardwareOffloadingStatus::kSupported
              : LowEnergyScanSessionHardwareOffloadingStatus::kNotSupported;
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 void BluetoothAdapterBlueZ::SetStandardChromeOSAdapterName() {
@@ -1813,9 +1813,9 @@
 }
 
 void BluetoothAdapterBlueZ::StopScan(DiscoverySessionResultCallback callback) {
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   ble_scan_parser_.reset();
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Not having an adapter qualifies as not scanning so we callback a success
   if (!IsPresent()) {
@@ -1905,7 +1905,7 @@
   // Report success on the original request and increment the count.
   BLUETOOTH_LOG(EVENT) << __func__;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   device::BluetoothAdapterFactory::BleScanParserCallback
       ble_scan_parser_callback =
           device::BluetoothAdapterFactory::GetBleScanParserCallback();
@@ -1923,7 +1923,7 @@
     logged_once = true;
 #endif  // DCHECK_IS_ON()
   }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   if (IsPresent()) {
     std::move(callback).Run(false,
@@ -2180,7 +2180,7 @@
   device->RemoveBatteryInfo(BatteryType::kDefault);
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothAdapterBlueZ::
     RegisterAdvertisementMonitorApplicationServiceProvider() {
   if (is_advertisement_monitor_application_provider_registered_ ||
@@ -2234,6 +2234,6 @@
   advertisement_monitor_application_provider_->RemoveMonitor(
       dbus::ObjectPath(session_id));
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 }  // namespace bluez
diff --git a/device/bluetooth/bluez/bluetooth_adapter_bluez.h b/device/bluetooth/bluez/bluetooth_adapter_bluez.h
index 6a061311..811a3ea7 100644
--- a/device/bluetooth/bluez/bluetooth_adapter_bluez.h
+++ b/device/bluetooth/bluez/bluetooth_adapter_bluez.h
@@ -36,14 +36,14 @@
 #include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
 #include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "device/bluetooth/bluetooth_low_energy_scan_filter.h"
 #include "device/bluetooth/bluetooth_low_energy_scan_session.h"
 #include "device/bluetooth/dbus/bluetooth_advertisement_monitor_manager_client.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/data_decoder/public/mojom/ble_scan_parser.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 namespace base {
 class TimeDelta;
@@ -60,10 +60,10 @@
 class BluetoothBlueZTest;
 class BluetoothAdapterProfileBlueZ;
 class BluetoothAdvertisementBlueZ;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 class BluetoothAdvertisementMonitorApplicationServiceProvider;
 class BluetoothAdvertisementMonitorServiceProvider;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 class BluetoothDeviceBlueZ;
 class BluetoothLocalGattCharacteristicBlueZ;
 class BluetoothLocalGattServiceBlueZ;
@@ -93,9 +93,9 @@
       public bluez::BluetoothDeviceClient::Observer,
       public bluez::BluetoothInputClient::Observer,
       public bluez::BluetoothAgentManagerClient::Observer,
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
       public bluez::BluetoothAdvertisementMonitorManagerClient::Observer,
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
       public bluez::BluetoothAgentServiceProvider::Delegate {
  public:
   using ErrorCompletionCallback =
@@ -106,10 +106,10 @@
   using ServiceRecordErrorCallback =
       base::OnceCallback<void(BluetoothServiceRecordBlueZ::ErrorCode)>;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   using ScanRecordPtr = data_decoder::mojom::ScanRecordPtr;
   using ScanRecordCallback = base::OnceCallback<void(ScanRecordPtr)>;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   static scoped_refptr<BluetoothAdapterBlueZ> CreateAdapter();
 
@@ -174,7 +174,7 @@
   device::BluetoothLocalGattService* GetGattService(
       const std::string& identifier) const override;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void SetServiceAllowList(const UUIDList& uuids,
                            base::OnceClosure callback,
                            ErrorCallback error_callback) override;
@@ -187,7 +187,7 @@
       std::unique_ptr<device::BluetoothLowEnergyScanFilter> filter,
       base::WeakPtr<device::BluetoothLowEnergyScanSession::Delegate> delegate)
       override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Set the adapter name to one chosen from the system information. Only Ash
@@ -229,7 +229,7 @@
                                          int16_t rssi,
                                          const std::vector<uint8_t>& eir);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   // Announce to observers advertisement received from |device|.
   void OnAdvertisementReceived(std::string device_address,
                                std::string device_name,
@@ -237,7 +237,7 @@
                                uint16_t device_appearance,
                                const dbus::ObjectPath& device_path,
                                ScanRecordPtr scan_record);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Announce to observers that |device| has changed its connected state.
   void NotifyDeviceConnectedStateChanged(BluetoothDeviceBlueZ* device,
@@ -360,10 +360,10 @@
   void AgentManagerAdded(const dbus::ObjectPath& object_path) override;
   void AgentManagerRemoved(const dbus::ObjectPath& object_path) override;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   // bluez::BluetoothAdvertisementMonitorManagerClient::Observer override.
   void SupportedAdvertisementMonitorFeaturesChanged() override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // bluez::BluetoothAgentServiceProvider::Delegate override.
   void Released() override;
@@ -530,14 +530,14 @@
   void UpdateDeviceBatteryLevelFromBatteryClient(
       const dbus::ObjectPath& object_path);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void RegisterAdvertisementMonitorApplicationServiceProvider();
   void OnRegisterAdvertisementMonitorApplicationServiceProvider();
 
   // Unregister the underlying advertisement monitor through
   // |advertisement_monitor_application_provider_|.
   void OnLowEnergyScanSessionDestroyed(const std::string& session_id);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   base::OnceClosure init_callback_;
 
@@ -599,7 +599,7 @@
   // crbug.com/687396.
   std::vector<scoped_refptr<BluetoothAdvertisementBlueZ>> advertisements_;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   // Timer used to schedule a second update to BlueZ's long term keys. This
   // second update is necessary in a first-time install situation, where field
   // trials might not yet have been available. By scheduling a second update
@@ -621,7 +621,7 @@
   // is registered.
   base::queue<std::unique_ptr<BluetoothAdvertisementMonitorServiceProvider>>
       pending_advertisement_monitors_;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
diff --git a/device/bluetooth/bluez/bluetooth_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_bluez_unittest.cc
index 565b94b..38f6c46 100644
--- a/device/bluetooth/bluez/bluetooth_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_bluez_unittest.cc
@@ -44,7 +44,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
@@ -56,7 +56,7 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "services/data_decoder/public/mojom/ble_scan_parser.mojom.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 namespace {
 
@@ -74,7 +74,7 @@
 using ::testing::_;
 using ::testing::StrictMock;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 // Background scanning filter values.
 constexpr int16_t kBackgroundScanningDeviceFoundRSSIThreshold = -80;
 constexpr int16_t kBackgroundScanningDeviceLostRSSIThreshold = -100;
@@ -110,7 +110,7 @@
                  ->GetBluetoothAdvertisementMonitorManagerClient())
       ->application_provider();
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 void ScheduleAsynchronousCancelPairing(BluetoothDevice* device) {
   base::SequencedTaskRunnerHandle::Get()->PostTask(
@@ -149,7 +149,7 @@
   return -1;
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 class FakeBleScanParserImpl : public data_decoder::mojom::BleScanParser {
  public:
   FakeBleScanParserImpl() = default;
@@ -165,7 +165,7 @@
     std::move(callback).Run(nullptr);
   }
 };
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 class FakeBluetoothProfileServiceProviderDelegate
     : public bluez::BluetoothProfileServiceProvider::Delegate {
@@ -187,7 +187,7 @@
   void Cancel() override {}
 };
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 class FakeBluetoothLowEnergyScanSessionDelegate
     : public device::BluetoothLowEnergyScanSession::Delegate {
  public:
@@ -257,12 +257,12 @@
   base::WeakPtrFactory<FakeBluetoothLowEnergyScanSessionDelegate>
       weak_ptr_factory_{this};
 };
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 }  // namespace
 
 class BluetoothBlueZTest : public testing::Test {
  public:
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   BluetoothBlueZTest() {
     scoped_feature_list_.InitWithFeatures(
         /*enabled_features=*/{chromeos::features::
@@ -318,7 +318,7 @@
     dbus_setter->SetBluetoothGattServiceClient(
         std::make_unique<bluez::FakeBluetoothGattServiceClient>());
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
     device::BluetoothAdapterFactory::SetBleScanParserCallback(
         base::BindLambdaForTesting([&]() {
           mojo::PendingRemote<data_decoder::mojom::BleScanParser>
@@ -328,7 +328,7 @@
               ble_scan_parser.InitWithNewPipeAndPassReceiver());
           return ble_scan_parser;
         }));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
     callback_count_ = 0;
     error_callback_count_ = 0;
@@ -336,10 +336,10 @@
   }
 
   void TearDown() override {
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
     device::BluetoothAdapterFactory::SetBleScanParserCallback(
         base::NullCallback());
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
     discovery_sessions_.clear();
     adapter_.reset();
@@ -496,7 +496,7 @@
   std::string last_client_error_;
   std::vector<std::unique_ptr<BluetoothDiscoverySession>> discovery_sessions_;
   BluetoothAdapterProfileBlueZ* adapter_profile_;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   base::HistogramTester histogram_tester_;
 #endif
 
@@ -507,7 +507,7 @@
     if (base::RunLoop::IsRunningOnCurrentThread())
       base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   base::test::ScopedFeatureList scoped_feature_list_;
 #endif
 };
@@ -2567,7 +2567,7 @@
   EXPECT_EQ(1, observer.device_removed_count());
   EXPECT_EQ(address, observer.last_device_address());
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   histogram_tester_.ExpectBucketCount("Bluetooth.ChromeOS.Forget.Result",
                                       device::ForgetResult::kSuccess, 1);
 #endif
@@ -2811,13 +2811,13 @@
   BluetoothDevice* device = adapter_->GetDevice(
       bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   bluez::FakeBluetoothDeviceClient::Properties* properties =
       fake_bluetooth_device_client_->GetProperties(dbus::ObjectPath(
           bluez::FakeBluetoothDeviceClient::kPairedDevicePath));
   properties->type.ReplaceValue(BluetoothDeviceClient::kTypeBredr);
   properties->type.set_valid(true);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   ASSERT_TRUE(device != nullptr);
   ASSERT_TRUE(device->IsPaired());
@@ -2849,7 +2849,7 @@
 
   EXPECT_FALSE(device->IsConnected());
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   histogram_tester_.ExpectBucketCount(
       "Bluetooth.ChromeOS.UserInitiatedDisconnect.Result",
       device::DisconnectResult::kSuccess, 1);
@@ -2858,7 +2858,7 @@
       device::DisconnectResult::kSuccess, 1);
   histogram_tester_.ExpectBucketCount("Bluetooth.ChromeOS.DeviceDisconnect",
                                       device->GetDeviceType(), 1);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 }
 
 TEST_F(BluetoothBlueZTest, DisconnectUnconnectedDevice) {
@@ -4874,7 +4874,7 @@
                              uuidLaterAdv, uuidLaterServ, uuidLaterBoth,
                              uuidAlwaysAdv, uuidAlwaysServ, uuidAlwaysBoth));
 }
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 TEST_F(BluetoothBlueZTest, StartLowEnergyScanSessionAdapterPresent) {
   GetAdapter();
 
@@ -5155,6 +5155,6 @@
             BluetoothAdapter::LowEnergyScanSessionHardwareOffloadingStatus::
                 kUndetermined);
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 }  // namespace bluez
diff --git a/device/bluetooth/bluez/bluetooth_device_bluez.cc b/device/bluetooth/bluez/bluetooth_device_bluez.cc
index 4ff7c36..efb9f2e 100644
--- a/device/bluetooth/bluez/bluetooth_device_bluez.cc
+++ b/device/bluetooth/bluez/bluetooth_device_bluez.cc
@@ -16,7 +16,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "build/chromeos_buildflags.h"
 #include "components/device_event_log/device_event_log.h"
 #include "dbus/bus.h"
 #include "device/bluetooth/bluetooth_socket.h"
@@ -37,7 +36,7 @@
 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "device/bluetooth/chromeos/bluetooth_utils.h"
 #endif
 
@@ -126,7 +125,7 @@
 }
 
 void OnForgetSuccess(base::OnceClosure callback) {
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   device::RecordForgetResult(device::ForgetResult::kSuccess);
 #endif
   std::move(callback).Run();
@@ -136,7 +135,7 @@
                    bluez::BluetoothDeviceBlueZ::ErrorCallback error_callback,
                    const std::string& error_name,
                    const std::string& error_message) {
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   device::RecordForgetResult(device::ForgetResult::kFailure);
 #endif
   BLUETOOTH_LOG(ERROR) << object_path.value()
@@ -232,7 +231,7 @@
     absl::optional<BluetoothUUID> service_uuid) {
 // Once ConnectLE is supported on Linux, this buildflag will not be necessary
 // (this bluez code is only run on Chrome OS and Linux).
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   if (num_connecting_calls_++ == 0)
     adapter()->NotifyDeviceChanged(this);
 
@@ -297,7 +296,7 @@
 
 // Once DisconnectLE is supported on Linux, this buildflag will not be necessary
 // (this bluez code is only run on Chrome OS and Linux).
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->DisconnectLE(
       object_path_, base::DoNothing(),
       base::BindOnce(&BluetoothDeviceBlueZ::OnDisconnectLEError,
@@ -309,7 +308,7 @@
 
 // Once DisconnectLE is supported on Linux, this buildflag will not be necessary
 // (this bluez code is only run on Chrome OS and Linux).
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothDeviceBlueZ::OnDisconnectLEError(
     const std::string& error_name,
     const std::string& error_message) {
@@ -434,7 +433,7 @@
 bool BluetoothDeviceBlueZ::IsGattConnected() const {
 // Once the |connected_le| property is supported on Linux, this buildflag will
 // not be necessary (this bluez code is only run on Chrome OS and Linux).
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   bluez::BluetoothDeviceClient::Properties* properties =
       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
           object_path_);
@@ -774,7 +773,7 @@
                      std::move(error_callback)));
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothDeviceBlueZ::ExecuteWrite(
     base::OnceClosure callback,
     ExecuteWriteErrorCallback error_callback) {
@@ -1039,7 +1038,7 @@
   std::move(error_callback).Run(code);
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothDeviceBlueZ::OnExecuteWriteError(
     ExecuteWriteErrorCallback error_callback,
     const std::string& error_name,
@@ -1222,7 +1221,7 @@
 }
 
 void BluetoothDeviceBlueZ::OnDisconnect(base::OnceClosure callback) {
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   device::RecordUserInitiatedDisconnectResult(
       device::DisconnectResult::kSuccess,
       /*transport=*/GetType());
@@ -1234,7 +1233,7 @@
 void BluetoothDeviceBlueZ::OnDisconnectError(ErrorCallback error_callback,
                                              const std::string& error_name,
                                              const std::string& error_message) {
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   device::RecordUserInitiatedDisconnectResult(
       device::DisconnectResult::kFailure,
       /*transport=*/GetType());
diff --git a/device/bluetooth/bluez/bluetooth_device_bluez.h b/device/bluetooth/bluez/bluetooth_device_bluez.h
index cd983060..15e58d2f 100644
--- a/device/bluetooth/bluez/bluetooth_device_bluez.h
+++ b/device/bluetooth/bluez/bluetooth_device_bluez.h
@@ -15,7 +15,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/task/sequenced_task_runner.h"
-#include "build/chromeos_buildflags.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_common.h"
 #include "device/bluetooth/bluetooth_device.h"
@@ -112,12 +111,12 @@
   bool IsGattServicesDiscoveryComplete() const override;
   void Pair(device::BluetoothDevice::PairingDelegate* pairing_delegate,
             ConnectCallback callback) override;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void ExecuteWrite(base::OnceClosure callback,
                     ExecuteWriteErrorCallback error_callback) override;
   void AbortWrite(base::OnceClosure callback,
                   AbortWriteErrorCallback error_callback) override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Invoked after a ConnectToService() or ConnectToServiceInsecurely() error,
   // to allow us to perform error handling before we invoke the
@@ -238,7 +237,7 @@
                                 const std::string& error_name,
                                 const std::string& error_message);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void OnExecuteWriteError(ExecuteWriteErrorCallback error_callback,
                            const std::string& error_name,
                            const std::string& error_message);
@@ -246,7 +245,7 @@
   void OnAbortWriteError(AbortWriteErrorCallback error_callback,
                          const std::string& error_name,
                          const std::string& error_message);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Internal methods to initiate a connection to this device, and methods
   // called by dbus:: on completion of the D-Bus method call.
@@ -261,10 +260,10 @@
 
 // Once DisconnectLE is supported on Linux, this buildflag will not be necessary
 // (this bluez code is only run on Chrome OS and Linux).
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void OnDisconnectLEError(const std::string& error_name,
                            const std::string& error_message);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Called by dbus:: on completion of the D-Bus method call to pair the device,
   // made inside |Connect()| and |ConnectClassic()|.
diff --git a/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
index 1620a41..db482c95 100644
--- a/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/run_loop.h"
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
-#include "build/chromeos_buildflags.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
@@ -2226,7 +2225,7 @@
   EXPECT_TRUE(update_sessions_[0]->IsActive());
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 TEST_F(BluetoothGattBlueZTest, ReliableWrite) {
   fake_bluetooth_device_client_->CreateDevice(
       dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
@@ -2373,7 +2372,7 @@
   base::RunLoop().Run();
   EXPECT_EQ(2, observer.gatt_characteristic_value_changed_count());
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 TEST_F(BluetoothGattBlueZTest, MultipleDevices) {
   fake_bluetooth_device_client_->CreateDevice(
diff --git a/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc b/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc
index 3c23cc1..95fb53f 100644
--- a/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc
+++ b/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc
@@ -14,7 +14,6 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
-#include "build/chromeos_buildflags.h"
 #include "dbus/property.h"
 #include "device/bluetooth/bluetooth_device.h"
 #include "device/bluetooth/bluetooth_gatt_characteristic.h"
@@ -220,7 +219,7 @@
                          std::move(error_callback)));
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothRemoteGattCharacteristicBlueZ::PrepareWriteRemoteCharacteristic(
     const std::vector<uint8_t>& value,
     base::OnceClosure callback,
@@ -238,22 +237,22 @@
                          weak_ptr_factory_.GetWeakPtr(),
                          std::move(error_callback)));
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 void BluetoothRemoteGattCharacteristicBlueZ::SubscribeToNotifications(
     device::BluetoothRemoteGattDescriptor* ccc_descriptor,
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
     NotificationType notification_type,
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
     base::OnceClosure callback,
     ErrorCallback error_callback) {
   bluez::BluezDBusManager::Get()
       ->GetBluetoothGattCharacteristicClient()
       ->StartNotify(
           object_path(),
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
           notification_type,
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
           base::BindOnce(
               &BluetoothRemoteGattCharacteristicBlueZ::OnStartNotifySuccess,
               weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
diff --git a/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h b/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h
index 9b39d53..87b21a81 100644
--- a/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h
+++ b/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h
@@ -16,7 +16,6 @@
 
 #include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
-#include "build/chromeos_buildflags.h"
 #include "dbus/object_path.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
 #include "device/bluetooth/bluetooth_remote_gatt_service.h"
@@ -68,14 +67,14 @@
       const std::vector<uint8_t>& value,
       base::OnceClosure callback,
       ErrorCallback error_callback) override;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void PrepareWriteRemoteCharacteristic(const std::vector<uint8_t>& value,
                                         base::OnceClosure callback,
                                         ErrorCallback error_callback) override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
  protected:
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void SubscribeToNotifications(
       device::BluetoothRemoteGattDescriptor* ccc_descriptor,
       NotificationType notification_type,
@@ -86,7 +85,7 @@
       device::BluetoothRemoteGattDescriptor* ccc_descriptor,
       base::OnceClosure callback,
       ErrorCallback error_callback) override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
   void UnsubscribeFromNotifications(
       device::BluetoothRemoteGattDescriptor* ccc_descriptor,
       base::OnceClosure callback,
diff --git a/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc
index 4b16baf..53005f5 100644
--- a/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc
+++ b/device/bluetooth/dbus/bluetooth_dbus_client_bundle.cc
@@ -11,7 +11,6 @@
 #include "base/logging.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
-#include "build/chromeos_buildflags.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "device/bluetooth/dbus/bluetooth_adapter_client.h"
 #include "device/bluetooth/dbus/bluetooth_admin_policy_client.h"
@@ -51,12 +50,12 @@
     bluetooth_admin_policy_client_ = BluetoothAdminPolicyClient::Create();
     bluetooth_le_advertising_manager_client_.reset(
         BluetoothLEAdvertisingManagerClient::Create());
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
     if (chromeos::features::IsBluetoothAdvertisementMonitoringEnabled()) {
       bluetooth_advertisement_monitor_manager_client_ =
           BluetoothAdvertisementMonitorManagerClient::Create();
     }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
     bluetooth_agent_manager_client_.reset(
         BluetoothAgentManagerClient::Create());
     bluetooth_battery_client_.reset(BluetoothBatteryClient::Create());
@@ -86,12 +85,12 @@
         std::make_unique<FakeBluetoothAdminPolicyClient>();
     bluetooth_le_advertising_manager_client_ =
         std::make_unique<FakeBluetoothLEAdvertisingManagerClient>();
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
     if (chromeos::features::IsBluetoothAdvertisementMonitoringEnabled()) {
       bluetooth_advertisement_monitor_manager_client_ =
           std::make_unique<FakeBluetoothAdvertisementMonitorManagerClient>();
     }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
     bluetooth_agent_manager_client_ =
         std::make_unique<FakeBluetoothAgentManagerClient>();
     bluetooth_battery_client_ = std::make_unique<FakeBluetoothBatteryClient>();
diff --git a/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
index b62076a..ed22cb13c 100644
--- a/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
@@ -11,7 +11,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/values.h"
-#include "build/chromeos_buildflags.h"
 #include "dbus/bus.h"
 #include "dbus/object_manager.h"
 #include "dbus/values_util.h"
@@ -187,9 +186,9 @@
   // BluetoothGattCharacteristicClient override.
   void StartNotify(
       const dbus::ObjectPath& object_path,
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
       device::BluetoothGattCharacteristic::NotificationType notification_type,
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
       base::OnceClosure callback,
       ErrorCallback error_callback) override {
     dbus::ObjectProxy* object_proxy =
@@ -202,10 +201,10 @@
     dbus::MethodCall method_call(
         bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
         bluetooth_gatt_characteristic::kStartNotify);
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
     dbus::MessageWriter writer(&method_call);
     writer.AppendByte(static_cast<uint8_t>(notification_type));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
     object_proxy->CallMethodWithErrorCallback(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
diff --git a/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h
index c6c423f2..d7ff31b 100644
--- a/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h
+++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "base/callback.h"
-#include "build/chromeos_buildflags.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
 #include "device/bluetooth/bluetooth_export.h"
@@ -132,7 +131,7 @@
   // Starts a notification session from this characteristic with object path
   // |object_path| if it supports value notifications or indications. Invokes
   // |callback| on success and |error_callback| on failure.
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   virtual void StartNotify(
       const dbus::ObjectPath& object_path,
       device::BluetoothGattCharacteristic::NotificationType notification_type,
@@ -142,7 +141,7 @@
   virtual void StartNotify(const dbus::ObjectPath& object_path,
                            base::OnceClosure callback,
                            ErrorCallback error_callback) = 0;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Cancels any previous StartNotify transaction for characteristic with
   // object path |object_path|. Invokes |callback| on success and
diff --git a/device/bluetooth/dbus/bluez_dbus_manager.cc b/device/bluetooth/dbus/bluez_dbus_manager.cc
index dd52ee77..964b095 100644
--- a/device/bluetooth/dbus/bluez_dbus_manager.cc
+++ b/device/bluetooth/dbus/bluez_dbus_manager.cc
@@ -15,7 +15,6 @@
 #include "base/system/sys_info.h"
 #include "base/threading/thread.h"
 #include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "dbus/bus.h"
 #include "dbus/dbus_statistics.h"
@@ -57,9 +56,9 @@
   // On Chrome OS, Bluez might not be ready by the time we initialize the
   // BluezDBusManager so we initialize the clients anyway.
   bool should_check_object_manager = true;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   should_check_object_manager = false;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   if (!use_dbus_fakes) {
     // Make sure that Floss manager daemon is in agreement with Chrome about the
@@ -255,12 +254,12 @@
                                                    bluetooth_service_name);
   client_bundle_->bluetooth_admin_policy_client()->Init(GetSystemBus(),
                                                         bluetooth_service_name);
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   if (chromeos::features::IsBluetoothAdvertisementMonitoringEnabled()) {
     client_bundle_->bluetooth_advertisement_monitor_manager_client()->Init(
         GetSystemBus(), bluetooth_service_name);
   }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
   client_bundle_->bluetooth_agent_manager_client()->Init(
       GetSystemBus(), bluetooth_service_name);
   client_bundle_->bluetooth_device_client()->Init(GetSystemBus(),
@@ -306,7 +305,7 @@
 
   BluezDBusThreadManager::Initialize();
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   DCHECK(system_bus);
   // On ChromeOS, BluetoothSystem needs a separate connection to Bluez, so we
   // use BluezDBusThreadManager to get two different connections to the same
@@ -365,10 +364,10 @@
   g_bluez_dbus_manager = nullptr;
   delete dbus_manager;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   if (!g_using_bluez_dbus_manager_for_testing)
     BluezDBusThreadManager::Shutdown();
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   g_using_bluez_dbus_manager_for_testing = false;
   DVLOG(1) << "BluezDBusManager Shutdown completed";
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
index 4d5fc5ac..18c96d3d 100644
--- a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
@@ -14,7 +14,6 @@
 #include "base/task/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
 #include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
 #include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h"
@@ -330,9 +329,9 @@
 
 void FakeBluetoothGattCharacteristicClient::StartNotify(
     const dbus::ObjectPath& object_path,
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
     device::BluetoothGattCharacteristic::NotificationType notification_type,
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
     base::OnceClosure callback,
     ErrorCallback error_callback) {
   if (!IsHeartRateVisible()) {
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
index 11cecef..125e5a3 100644
--- a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
@@ -14,7 +14,6 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "build/chromeos_buildflags.h"
 #include "dbus/object_path.h"
 #include "dbus/property.h"
 #include "device/bluetooth/bluetooth_export.h"
@@ -70,7 +69,7 @@
                          const std::vector<uint8_t>& value,
                          base::OnceClosure callback,
                          ErrorCallback error_callback) override;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void StartNotify(
       const dbus::ObjectPath& object_path,
       device::BluetoothGattCharacteristic::NotificationType notification_type,
@@ -80,7 +79,7 @@
   void StartNotify(const dbus::ObjectPath& object_path,
                    base::OnceClosure callback,
                    ErrorCallback error_callback) override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   void StopNotify(const dbus::ObjectPath& object_path,
                   base::OnceClosure callback,
diff --git a/device/bluetooth/floss/bluetooth_adapter_floss.cc b/device/bluetooth/floss/bluetooth_adapter_floss.cc
index 77c45e0..a7b46a9 100644
--- a/device/bluetooth/floss/bluetooth_adapter_floss.cc
+++ b/device/bluetooth/floss/bluetooth_adapter_floss.cc
@@ -763,7 +763,7 @@
   return nullptr;
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothAdapterFloss::SetServiceAllowList(const UUIDList& uuids,
                                                 base::OnceClosure callback,
                                                 ErrorCallback error_callback) {
@@ -783,7 +783,7 @@
   NOTIMPLEMENTED();
   return LowEnergyScanSessionHardwareOffloadingStatus::kNotSupported;
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 void BluetoothAdapterFloss::SetStandardChromeOSAdapterName() {
diff --git a/device/bluetooth/floss/bluetooth_adapter_floss.h b/device/bluetooth/floss/bluetooth_adapter_floss.h
index f6ad020..930b32d 100644
--- a/device/bluetooth/floss/bluetooth_adapter_floss.h
+++ b/device/bluetooth/floss/bluetooth_adapter_floss.h
@@ -21,10 +21,10 @@
 #include "device/bluetooth/floss/floss_dbus_client.h"
 #include "device/bluetooth/floss/floss_manager_client.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "device/bluetooth/bluetooth_low_energy_scan_filter.h"
 #include "device/bluetooth/bluetooth_low_energy_scan_session.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 namespace floss {
 
@@ -104,7 +104,7 @@
   device::BluetoothLocalGattService* GetGattService(
       const std::string& identifier) const override;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void SetServiceAllowList(const UUIDList& uuids,
                            base::OnceClosure callback,
                            ErrorCallback error_callback) override;
@@ -117,7 +117,7 @@
       std::unique_ptr<device::BluetoothLowEnergyScanFilter> filter,
       base::WeakPtr<device::BluetoothLowEnergyScanSession::Delegate> delegate)
       override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Set the adapter name to one chosen from the system information. Only Ash
diff --git a/device/bluetooth/floss/bluetooth_device_floss.cc b/device/bluetooth/floss/bluetooth_device_floss.cc
index cbdd012b..4ff1a27 100644
--- a/device/bluetooth/floss/bluetooth_device_floss.cc
+++ b/device/bluetooth/floss/bluetooth_device_floss.cc
@@ -306,7 +306,7 @@
   NOTIMPLEMENTED();
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void BluetoothDeviceFloss::ExecuteWrite(
     base::OnceClosure callback,
     ExecuteWriteErrorCallback error_callback) {
@@ -317,7 +317,7 @@
                                       AbortWriteErrorCallback error_callback) {
   NOTIMPLEMENTED();
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 FlossDeviceId BluetoothDeviceFloss::AsFlossDeviceId() const {
   return FlossDeviceId{.address = address_, .name = name_};
diff --git a/device/bluetooth/floss/bluetooth_device_floss.h b/device/bluetooth/floss/bluetooth_device_floss.h
index 5da7992..f22e9af 100644
--- a/device/bluetooth/floss/bluetooth_device_floss.h
+++ b/device/bluetooth/floss/bluetooth_device_floss.h
@@ -9,7 +9,6 @@
 
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/bluetooth_common.h"
 #include "device/bluetooth/bluetooth_device.h"
 #include "device/bluetooth/bluetooth_export.h"
@@ -95,12 +94,12 @@
   bool IsGattServicesDiscoveryComplete() const override;
   void Pair(device::BluetoothDevice::PairingDelegate* pairing_delegate,
             ConnectCallback callback) override;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void ExecuteWrite(base::OnceClosure callback,
                     ExecuteWriteErrorCallback error_callback) override;
   void AbortWrite(base::OnceClosure callback,
                   AbortWriteErrorCallback error_callback) override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   FlossDeviceId AsFlossDeviceId() const;
   void SetName(const std::string& name);
diff --git a/device/bluetooth/test/fake_central.cc b/device/bluetooth/test/fake_central.cc
index 1116949..24bd2e26 100644
--- a/device/bluetooth/test/fake_central.cc
+++ b/device/bluetooth/test/fake_central.cc
@@ -21,9 +21,9 @@
 #include "device/bluetooth/test/fake_remote_gatt_characteristic.h"
 #include "device/bluetooth/test/fake_remote_gatt_service.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "device/bluetooth/bluetooth_low_energy_scan_filter.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 namespace bluetooth {
 
@@ -614,7 +614,7 @@
   return nullptr;
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void FakeCentral::SetServiceAllowList(const UUIDList& uuids,
                                       base::OnceClosure callback,
                                       ErrorCallback error_callback) {
@@ -633,7 +633,7 @@
 FakeCentral::GetLowEnergyScanSessionHardwareOffloadingStatus() {
   return LowEnergyScanSessionHardwareOffloadingStatus::kNotSupported;
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 void FakeCentral::SetStandardChromeOSAdapterName() {
diff --git a/device/bluetooth/test/fake_central.h b/device/bluetooth/test/fake_central.h
index 0b27424d..ea3b6ba6 100644
--- a/device/bluetooth/test/fake_central.h
+++ b/device/bluetooth/test/fake_central.h
@@ -16,10 +16,10 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "device/bluetooth/bluetooth_low_energy_scan_filter.h"
 #include "device/bluetooth/bluetooth_low_energy_scan_session.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 namespace bluetooth {
 
@@ -195,7 +195,7 @@
 #endif
   device::BluetoothLocalGattService* GetGattService(
       const std::string& identifier) const override;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void SetServiceAllowList(const UUIDList& uuids,
                            base::OnceClosure callback,
                            ErrorCallback error_callback) override;
@@ -206,7 +206,7 @@
       std::unique_ptr<device::BluetoothLowEnergyScanFilter> filter,
       base::WeakPtr<device::BluetoothLowEnergyScanSession::Delegate> delegate)
       override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   void SetStandardChromeOSAdapterName() override;
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/device/bluetooth/test/fake_peripheral.cc b/device/bluetooth/test/fake_peripheral.cc
index 6d9631c7..f017e9f 100644
--- a/device/bluetooth/test/fake_peripheral.cc
+++ b/device/bluetooth/test/fake_peripheral.cc
@@ -13,7 +13,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
 #include "device/bluetooth/test/fake_remote_gatt_service.h"
 
@@ -373,7 +372,7 @@
 void FakePeripheral::DisconnectGatt() {
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void FakePeripheral::ExecuteWrite(base::OnceClosure callback,
                                   ExecuteWriteErrorCallback error_callback) {
   NOTIMPLEMENTED();
@@ -383,6 +382,6 @@
                                 AbortWriteErrorCallback error_callback) {
   NOTIMPLEMENTED();
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 }  // namespace bluetooth
diff --git a/device/bluetooth/test/fake_peripheral.h b/device/bluetooth/test/fake_peripheral.h
index f1de0e2..cb773cf7 100644
--- a/device/bluetooth/test/fake_peripheral.h
+++ b/device/bluetooth/test/fake_peripheral.h
@@ -9,7 +9,6 @@
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/bluetooth_device.h"
 #include "device/bluetooth/test/fake_central.h"
 #include "device/bluetooth/test/fake_remote_gatt_service.h"
@@ -131,12 +130,12 @@
       GattConnectionCallback callback,
       absl::optional<device::BluetoothUUID> service_uuid) override;
   bool IsGattServicesDiscoveryComplete() const override;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void ExecuteWrite(base::OnceClosure callback,
                     ExecuteWriteErrorCallback error_callback) override;
   void AbortWrite(base::OnceClosure callback,
                   AbortWriteErrorCallback error_callback) override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
  protected:
   void CreateGattConnectionImpl(absl::optional<device::BluetoothUUID>) override;
diff --git a/device/bluetooth/test/fake_remote_gatt_characteristic.cc b/device/bluetooth/test/fake_remote_gatt_characteristic.cc
index e2d7c4d..e7dbbe2f 100644
--- a/device/bluetooth/test/fake_remote_gatt_characteristic.cc
+++ b/device/bluetooth/test/fake_remote_gatt_characteristic.cc
@@ -9,7 +9,6 @@
 
 #include "base/bind.h"
 #include "base/strings/stringprintf.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
 #include "device/bluetooth/test/fake_read_response.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -192,20 +191,20 @@
                      std::move(error_callback), value, write_type));
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void FakeRemoteGattCharacteristic::PrepareWriteRemoteCharacteristic(
     const std::vector<uint8_t>& value,
     base::OnceClosure callback,
     ErrorCallback error_callback) {
   NOTIMPLEMENTED();
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 void FakeRemoteGattCharacteristic::SubscribeToNotifications(
     device::BluetoothRemoteGattDescriptor* ccc_descriptor,
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
     NotificationType notification_type,
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
     base::OnceClosure callback,
     ErrorCallback error_callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/device/bluetooth/test/fake_remote_gatt_characteristic.h b/device/bluetooth/test/fake_remote_gatt_characteristic.h
index 29f0dbd..f51ee49a 100644
--- a/device/bluetooth/test/fake_remote_gatt_characteristic.h
+++ b/device/bluetooth/test/fake_remote_gatt_characteristic.h
@@ -11,7 +11,6 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
 #include "device/bluetooth/public/mojom/test/fake_bluetooth.mojom.h"
@@ -98,14 +97,14 @@
       const std::vector<uint8_t>& value,
       base::OnceClosure callback,
       ErrorCallback error_callback) override;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void PrepareWriteRemoteCharacteristic(const std::vector<uint8_t>& value,
                                         base::OnceClosure callback,
                                         ErrorCallback error_callback) override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
  protected:
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   // device::BluetoothRemoteGattCharacteristic overrides:
   void SubscribeToNotifications(
       device::BluetoothRemoteGattDescriptor* ccc_descriptor,
@@ -118,7 +117,7 @@
       device::BluetoothRemoteGattDescriptor* ccc_descriptor,
       base::OnceClosure callback,
       ErrorCallback error_callback) override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
   void UnsubscribeFromNotifications(
       device::BluetoothRemoteGattDescriptor* ccc_descriptor,
       base::OnceClosure callback,
diff --git a/device/bluetooth/test/mock_bluetooth_adapter.h b/device/bluetooth/test/mock_bluetooth_adapter.h
index 1aba420..2ef7adf 100644
--- a/device/bluetooth/test/mock_bluetooth_adapter.h
+++ b/device/bluetooth/test/mock_bluetooth_adapter.h
@@ -18,9 +18,9 @@
 #include "device/bluetooth/test/mock_bluetooth_device.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "device/bluetooth/bluetooth_low_energy_scan_filter.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 namespace device {
 
@@ -119,7 +119,7 @@
                     CreateServiceErrorCallback error_callback));
   MOCK_CONST_METHOD1(GetGattService,
                      BluetoothLocalGattService*(const std::string& identifier));
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   MOCK_METHOD3(SetServiceAllowList,
                void(const UUIDList& uuids,
                     base::OnceClosure callback,
@@ -131,7 +131,7 @@
       std::unique_ptr<BluetoothLowEnergyScanSession>(
           std::unique_ptr<BluetoothLowEnergyScanFilter> filter,
           base::WeakPtr<BluetoothLowEnergyScanSession::Delegate> delegate));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   MOCK_METHOD0(SetStandardChromeOSAdapterName, void());
diff --git a/device/bluetooth/test/mock_bluetooth_device.h b/device/bluetooth/test/mock_bluetooth_device.h
index 145c530..9d906eb 100644
--- a/device/bluetooth/test/mock_bluetooth_device.h
+++ b/device/bluetooth/test/mock_bluetooth_device.h
@@ -12,7 +12,6 @@
 #include <vector>
 
 #include "base/containers/queue.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/bluetooth_common.h"
 #include "device/bluetooth/bluetooth_device.h"
 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
@@ -130,14 +129,14 @@
   MOCK_METHOD1(CreateGattConnectionImpl,
                void(absl::optional<BluetoothUUID> service_uuid));
   MOCK_METHOD0(DisconnectGatt, void());
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   MOCK_METHOD2(ExecuteWrite,
                void(base::OnceClosure callback,
                     ExecuteWriteErrorCallback error_callback));
   MOCK_METHOD2(AbortWrite,
                void(base::OnceClosure callback,
                     AbortWriteErrorCallback error_callback));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // BluetoothDevice manages the lifetime of its BluetoothGATTServices.
   // This method takes ownership of the MockBluetoothGATTServices. This is only
diff --git a/device/bluetooth/test/mock_bluetooth_gatt_characteristic.h b/device/bluetooth/test/mock_bluetooth_gatt_characteristic.h
index 7454a13b..661a6bf 100644
--- a/device/bluetooth/test/mock_bluetooth_gatt_characteristic.h
+++ b/device/bluetooth/test/mock_bluetooth_gatt_characteristic.h
@@ -12,7 +12,6 @@
 #include <vector>
 
 #include "base/callback.h"
-#include "build/chromeos_buildflags.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
 #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h"
 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
@@ -52,7 +51,7 @@
                      std::vector<BluetoothRemoteGattDescriptor*>());
   MOCK_CONST_METHOD1(GetDescriptor,
                      BluetoothRemoteGattDescriptor*(const std::string&));
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void StartNotifySession(NotificationType t,
                           NotifySessionCallback c,
                           ErrorCallback ec) override {
@@ -60,7 +59,7 @@
   }
   MOCK_METHOD3(StartNotifySession_,
                void(NotificationType, NotifySessionCallback&, ErrorCallback&));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
   void StartNotifySession(NotifySessionCallback c, ErrorCallback ec) override {
     StartNotifySession_(c, ec);
   }
@@ -96,7 +95,7 @@
                void(const std::vector<uint8_t>&,
                     base::OnceClosure&,
                     ErrorCallback&));
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void PrepareWriteRemoteCharacteristic(const std::vector<uint8_t>& v,
                                         base::OnceClosure c,
                                         ErrorCallback ec) override {
@@ -106,13 +105,13 @@
                void(const std::vector<uint8_t>&,
                     base::OnceClosure&,
                     ErrorCallback&));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   void AddMockDescriptor(
       std::unique_ptr<MockBluetoothGattDescriptor> mock_descriptor);
 
  protected:
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void SubscribeToNotifications(BluetoothRemoteGattDescriptor* d,
                                 NotificationType t,
                                 base::OnceClosure c,
@@ -134,7 +133,7 @@
                void(BluetoothRemoteGattDescriptor*,
                     base::OnceClosure&,
                     ErrorCallback&));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
   void UnsubscribeFromNotifications(BluetoothRemoteGattDescriptor* d,
                                     base::OnceClosure c,
                                     ErrorCallback ec) override {
diff --git a/device/bluetooth/test/test_bluetooth_adapter_observer.cc b/device/bluetooth/test/test_bluetooth_adapter_observer.cc
index 7ad7262..31fc6f7 100644
--- a/device/bluetooth/test/test_bluetooth_adapter_observer.cc
+++ b/device/bluetooth/test/test_bluetooth_adapter_observer.cc
@@ -418,14 +418,14 @@
   QuitMessageLoop();
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void TestBluetoothAdapterObserver::
     LowEnergyScanSessionHardwareOffloadingStatusChanged(
         BluetoothAdapter::LowEnergyScanSessionHardwareOffloadingStatus status) {
   last_low_energy_scan_session_hardware_offloading_status_ = status;
   QuitMessageLoop();
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 void TestBluetoothAdapterObserver::QuitMessageLoop() {
   if (base::RunLoop::IsRunningOnCurrentThread())
diff --git a/device/bluetooth/test/test_bluetooth_adapter_observer.h b/device/bluetooth/test/test_bluetooth_adapter_observer.h
index 39e23f05..ff0d504 100644
--- a/device/bluetooth/test/test_bluetooth_adapter_observer.h
+++ b/device/bluetooth/test/test_bluetooth_adapter_observer.h
@@ -107,11 +107,11 @@
   void GattDescriptorValueChanged(BluetoothAdapter* adapter,
                                   BluetoothRemoteGattDescriptor* descriptor,
                                   const std::vector<uint8_t>& value) override;
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   void LowEnergyScanSessionHardwareOffloadingStatusChanged(
       BluetoothAdapter::LowEnergyScanSessionHardwareOffloadingStatus status)
       override;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   // Adapter related:
   int present_changed_count() const { return present_changed_count_; }
@@ -228,12 +228,12 @@
   std::vector<uint8_t> last_changed_descriptor_value() const {
     return last_changed_descriptor_value_;
   }
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   BluetoothAdapter::LowEnergyScanSessionHardwareOffloadingStatus
   last_low_energy_scan_session_hardware_offloading_status() const {
     return last_low_energy_scan_session_hardware_offloading_status_;
   }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
  private:
   // Some tests use a message loop since background processing is simulated;
@@ -306,12 +306,12 @@
   BluetoothUUID last_gatt_descriptor_uuid_;
   std::vector<uint8_t> last_changed_descriptor_value_;
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   BluetoothAdapter::LowEnergyScanSessionHardwareOffloadingStatus
       last_low_energy_scan_session_hardware_offloading_status_ =
           BluetoothAdapter::LowEnergyScanSessionHardwareOffloadingStatus::
               kUndetermined;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 };
 
 }  // namespace device
diff --git a/device/fido/cros/discovery.cc b/device/fido/cros/discovery.cc
index 7efb419..afe03c10 100644
--- a/device/fido/cros/discovery.cc
+++ b/device/fido/cros/discovery.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
+#include "build/chromeos_buildflags.h"
 #include "chromeos/dbus/u2f/u2f_client.h"
 #include "components/device_event_log/device_event_log.h"
 
diff --git a/device/gamepad/BUILD.gn b/device/gamepad/BUILD.gn
index 7d29de20..15a232a 100644
--- a/device/gamepad/BUILD.gn
+++ b/device/gamepad/BUILD.gn
@@ -205,6 +205,7 @@
     ]
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
     ]
     annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/device/gamepad/gamepad_device_linux.cc b/device/gamepad/gamepad_device_linux.cc
index dde1650..38b9026 100644
--- a/device/gamepad/gamepad_device_linux.cc
+++ b/device/gamepad/gamepad_device_linux.cc
@@ -17,7 +17,6 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "build/chromeos_buildflags.h"
 #include "device/gamepad/dualshock4_controller.h"
 #include "device/gamepad/gamepad_data_fetcher.h"
 #include "device/gamepad/hid_haptic_gamepad.h"
@@ -25,9 +24,9 @@
 #include "device/gamepad/xbox_hid_controller.h"
 #include "device/udev_linux/udev.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 #include "chromeos/dbus/permission_broker/permission_broker_client.h"  // nogncheck
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 namespace device {
 
@@ -198,7 +197,7 @@
   return static_cast<uint16_t>(out);
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
 void OnOpenPathSuccess(
     chromeos::PermissionBrokerClient::OpenPathCallback callback,
     scoped_refptr<base::SequencedTaskRunner> polling_runner,
@@ -230,7 +229,7 @@
   client->OpenPath(path, std::move(success_callback),
                    std::move(error_callback));
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
 // Small helper to avoid constructing a StringPiece from nullptr.
 base::StringPiece ToStringPiece(const char* str) {
@@ -567,7 +566,7 @@
 
   auto fd = base::ScopedFD(open(pad_info.path.c_str(), O_RDWR | O_NONBLOCK));
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS)
   // If we failed to open the device it may be due to insufficient permissions.
   // Try again using the PermissionBrokerClient.
   if (!fd.is_valid()) {
@@ -582,7 +581,7 @@
                        std::move(open_path_callback), polling_runner_));
     return;
   }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
   OnOpenHidrawNodeComplete(std::move(callback), std::move(fd));
 }
diff --git a/device/vr/BUILD.gn b/device/vr/BUILD.gn
index bb6e85f7..2a2d8ad 100644
--- a/device/vr/BUILD.gn
+++ b/device/vr/BUILD.gn
@@ -361,6 +361,7 @@
     sources = java_sources_needing_jni
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/gvr-android-sdk:gvr_common_java",
       "//ui/android:ui_java",
     ]
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_condition.cc b/extensions/browser/api/declarative_webrequest/webrequest_condition.cc
index e9e07ad..237396c 100644
--- a/extensions/browser/api/declarative_webrequest/webrequest_condition.cc
+++ b/extensions/browser/api/declarative_webrequest/webrequest_condition.cc
@@ -120,15 +120,15 @@
     URLMatcherConditionFactory* url_matcher_condition_factory,
     const base::Value& condition,
     std::string* error) {
-  const base::DictionaryValue* condition_dict = NULL;
-  if (!condition.GetAsDictionary(&condition_dict)) {
+  const base::Value::Dict* condition_dict = condition.GetIfDict();
+  if (!condition_dict) {
     *error = kExpectedDictionary;
     return nullptr;
   }
 
   // Verify that we are dealing with a Condition whose type we understand.
   const std::string* instance_type =
-      condition_dict->FindStringKey(keys::kInstanceTypeKey);
+      condition_dict->FindString(keys::kInstanceTypeKey);
   if (!instance_type) {
     *error = kConditionWithoutInstanceType;
     return nullptr;
@@ -141,24 +141,23 @@
   WebRequestConditionAttributes attributes;
   scoped_refptr<URLMatcherConditionSet> url_matcher_condition_set;
 
-  for (base::DictionaryValue::Iterator iter(*condition_dict);
-       !iter.IsAtEnd(); iter.Advance()) {
-    const std::string& condition_attribute_name = iter.key();
-    const base::Value& condition_attribute_value = iter.value();
+  for (const auto entry : *condition_dict) {
+    const std::string& condition_attribute_name = entry.first;
+    const base::Value& condition_attribute_value = entry.second;
     if (condition_attribute_name == keys::kInstanceTypeKey ||
         condition_attribute_name ==
             keys::kDeprecatedFirstPartyForCookiesUrlKey ||
         condition_attribute_name == keys::kDeprecatedThirdPartyKey) {
       // Skip this.
     } else if (condition_attribute_name == keys::kUrlKey) {
-      const base::DictionaryValue* dict = NULL;
-      if (!condition_attribute_value.GetAsDictionary(&dict)) {
+      const base::Value::Dict* dict = condition_attribute_value.GetIfDict();
+      if (!dict) {
         *error = base::StringPrintf(kInvalidTypeOfParamter,
                                     condition_attribute_name.c_str());
       } else {
         url_matcher_condition_set =
             URLMatcherFactory::CreateFromURLFilterDictionary(
-                url_matcher_condition_factory, dict, ++g_next_id, error);
+                url_matcher_condition_factory, *dict, ++g_next_id, error);
       }
     } else {
       scoped_refptr<const WebRequestConditionAttribute> attribute =
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute.cc b/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute.cc
index 2e28f71..d4d458e 100644
--- a/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute.cc
+++ b/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute.cc
@@ -31,7 +31,6 @@
 #include "net/http/http_util.h"
 
 using base::CaseInsensitiveCompareASCII;
-using base::DictionaryValue;
 using base::ListValue;
 using base::Value;
 
@@ -335,7 +334,7 @@
     // Gets the test group description in |tests| and creates the corresponding
     // HeaderMatchTest. On failure returns null.
     static std::unique_ptr<const HeaderMatchTest> Create(
-        const base::DictionaryValue* tests);
+        const base::Value::Dict& tests);
 
     // Does the header "|name|: |value|" match all tests in |this|?
     bool Matches(const std::string& name, const std::string& value) const;
@@ -367,12 +366,12 @@
     const base::Value::ConstListView tests) {
   std::vector<std::unique_ptr<const HeaderMatchTest>> header_tests;
   for (const auto& entry : tests) {
-    const base::DictionaryValue* tests_dict = nullptr;
-    if (!entry.GetAsDictionary(&tests_dict))
+    const base::Value::Dict* tests_dict = entry.GetIfDict();
+    if (!tests_dict)
       return nullptr;
 
     std::unique_ptr<const HeaderMatchTest> header_test(
-        HeaderMatchTest::Create(tests_dict));
+        HeaderMatchTest::Create(*tests_dict));
     if (header_test.get() == nullptr)
       return nullptr;
     header_tests.push_back(std::move(header_test));
@@ -451,39 +450,38 @@
 
 // static
 std::unique_ptr<const HeaderMatcher::HeaderMatchTest>
-HeaderMatcher::HeaderMatchTest::Create(const base::DictionaryValue* tests) {
+HeaderMatcher::HeaderMatchTest::Create(const base::Value::Dict& tests) {
   std::vector<std::unique_ptr<const StringMatchTest>> name_match;
   std::vector<std::unique_ptr<const StringMatchTest>> value_match;
 
-  for (base::DictionaryValue::Iterator it(*tests);
-       !it.IsAtEnd(); it.Advance()) {
+  for (const auto entry : tests) {
     bool is_name = false;  // Is this test for header name?
     StringMatchTest::MatchType match_type;
-    if (it.key() == keys::kNamePrefixKey) {
+    if (entry.first == keys::kNamePrefixKey) {
       is_name = true;
       match_type = StringMatchTest::kPrefix;
-    } else if (it.key() == keys::kNameSuffixKey) {
+    } else if (entry.first == keys::kNameSuffixKey) {
       is_name = true;
       match_type = StringMatchTest::kSuffix;
-    } else if (it.key() == keys::kNameContainsKey) {
+    } else if (entry.first == keys::kNameContainsKey) {
       is_name = true;
       match_type = StringMatchTest::kContains;
-    } else if (it.key() == keys::kNameEqualsKey) {
+    } else if (entry.first == keys::kNameEqualsKey) {
       is_name = true;
       match_type = StringMatchTest::kEquals;
-    } else if (it.key() == keys::kValuePrefixKey) {
+    } else if (entry.first == keys::kValuePrefixKey) {
       match_type = StringMatchTest::kPrefix;
-    } else if (it.key() == keys::kValueSuffixKey) {
+    } else if (entry.first == keys::kValueSuffixKey) {
       match_type = StringMatchTest::kSuffix;
-    } else if (it.key() == keys::kValueContainsKey) {
+    } else if (entry.first == keys::kValueContainsKey) {
       match_type = StringMatchTest::kContains;
-    } else if (it.key() == keys::kValueEqualsKey) {
+    } else if (entry.first == keys::kValueEqualsKey) {
       match_type = StringMatchTest::kEquals;
     } else {
       NOTREACHED();  // JSON schema type checking should prevent this.
       return nullptr;
     }
-    const base::Value* content = &it.value();
+    const base::Value* content = &entry.second;
 
     std::vector<std::unique_ptr<const StringMatchTest>>* matching_tests =
         is_name ? &name_match : &value_match;
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc b/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc
index a41708a2..4d784dd 100644
--- a/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc
+++ b/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc
@@ -19,7 +19,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-using base::DictionaryValue;
 using base::ListValue;
 using base::Value;
 
@@ -244,27 +243,27 @@
 }
 
 // Builds a base::Value::Dict from an array of the form {name1, value1, name2,
-// value2, ...}. Values for the same key are grouped in a ListValue.
-base::Value::Dict GetDictionaryFromArray(
+// value2, ...}. Values for the same key are grouped in a List.
+base::Value::Dict GetDictFromArray(
     const std::vector<const std::string*>& array) {
   const size_t length = array.size();
   CHECK(length % 2 == 0);
 
-  base::Value::Dict dictionary;
+  base::Value::Dict dict;
   for (size_t i = 0; i < length; i += 2) {
     const std::string* name = array[i];
     const std::string* value = array[i+1];
-    if (base::Value* entry = dictionary.Find(*name)) {
+    if (base::Value* entry = dict.Find(*name)) {
       absl::optional<base::Value> entry_owned;
       switch (entry->type()) {
         case base::Value::Type::STRING: {
           // Replace the present string with a list.
           base::Value list(base::Value::Type::LIST);
           // No need to check again, we already verified the entry is there.
-          entry_owned = dictionary.Extract(*name);
+          entry_owned = dict.Extract(*name);
           list.Append(std::move(*entry_owned));
           list.Append(*value);
-          dictionary.Set(*name, std::move(list));
+          dict.Set(*name, std::move(list));
           break;
         }
         case base::Value::Type::LIST:  // Just append to the list.
@@ -275,10 +274,10 @@
           return base::Value::Dict();
       }
     } else {
-      dictionary.Set(*name, *value);
+      dict.Set(*name, *value);
     }
   }
-  return dictionary;
+  return dict;
 }
 
 // Returns whether the response headers from |request_info| satisfy the match
@@ -291,8 +290,7 @@
                    bool* result) {
   base::ListValue contains_headers;
   for (const auto& test : tests) {
-    base::Value::Dict temp = GetDictionaryFromArray(test);
-    contains_headers.Append(base::Value(std::move(temp)));
+    contains_headers.Append(base::Value(GetDictFromArray(test)));
   }
 
   std::string error;
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
index 3cb5eb6..13b1fcb 100644
--- a/extensions/browser/process_manager.cc
+++ b/extensions/browser/process_manager.cc
@@ -1047,13 +1047,6 @@
   return all_extension_workers_.Contains(worker_id);
 }
 
-std::vector<WorkerId> ProcessManager::GetServiceWorkers(
-    const ExtensionId& extension_id,
-    int render_process_id) const {
-  return all_extension_workers_.GetAllForExtension(extension_id,
-                                                   render_process_id);
-}
-
 std::vector<WorkerId> ProcessManager::GetServiceWorkersForExtension(
     const ExtensionId& extension_id) const {
   return all_extension_workers_.GetAllForExtension(extension_id);
diff --git a/extensions/browser/process_manager.h b/extensions/browser/process_manager.h
index 4974eb75..5fb4f98 100644
--- a/extensions/browser/process_manager.h
+++ b/extensions/browser/process_manager.h
@@ -237,11 +237,6 @@
   // |worker_id|.
   bool HasServiceWorker(const WorkerId& worker_id) const;
 
-  // Returns all the Service Worker infos that is active in the given render
-  // process for the extension with |extension_id|.
-  std::vector<WorkerId> GetServiceWorkers(const ExtensionId& extension_id,
-                                          int render_process_id) const;
-
   // Returns all the Service Worker infos that is active for the extension with
   // |extension_id|.
   std::vector<WorkerId> GetServiceWorkersForExtension(
diff --git a/extensions/common/event_filter.cc b/extensions/common/event_filter.cc
index 2f6b33d..74eb0da7 100644
--- a/extensions/common/event_filter.cc
+++ b/extensions/common/event_filter.cc
@@ -92,21 +92,21 @@
   if (url_filter_count == 0) {
     // If there are no URL filters then we want to match all events, so create a
     // URLFilter from an empty dictionary.
-    base::DictionaryValue empty_dict;
-    return AddDictionaryAsConditionSet(&empty_dict, condition_sets);
+    base::Value::Dict empty_dict;
+    return AddDictionaryAsConditionSet(empty_dict, condition_sets);
   }
   for (int i = 0; i < url_filter_count; i++) {
-    const base::DictionaryValue* url_filter;
-    if (!matcher->GetURLFilter(i, &url_filter))
+    const base::Value::Dict* url_filter = matcher->GetURLFilter(i);
+    if (!url_filter)
       return false;
-    if (!AddDictionaryAsConditionSet(url_filter, condition_sets))
+    if (!AddDictionaryAsConditionSet(*url_filter, condition_sets))
       return false;
   }
   return true;
 }
 
 bool EventFilter::AddDictionaryAsConditionSet(
-    const base::DictionaryValue* url_filter,
+    const base::Value::Dict& url_filter,
     URLMatcherConditionSet::Vector* condition_sets) {
   std::string error;
   URLMatcherConditionSet::ID condition_set_id = next_condition_set_id_++;
diff --git a/extensions/common/event_filter.h b/extensions/common/event_filter.h
index f3a944a..cf0ec5c 100644
--- a/extensions/common/event_filter.h
+++ b/extensions/common/event_filter.h
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/memory/raw_ptr.h"
+#include "base/values.h"
 #include "components/url_matcher/url_matcher.h"
 #include "extensions/common/event_matcher.h"
 #include "extensions/common/mojom/event_dispatcher.mojom-forward.h"
@@ -105,7 +106,7 @@
       url_matcher::URLMatcherConditionSet::Vector* condition_sets);
 
   bool AddDictionaryAsConditionSet(
-      const base::DictionaryValue* url_filter,
+      const base::Value::Dict& url_filter,
       url_matcher::URLMatcherConditionSet::Vector* condition_sets);
 
   url_matcher::URLMatcher url_matcher_;
diff --git a/extensions/common/event_matcher.cc b/extensions/common/event_matcher.cc
index c3db186..659c24f 100644
--- a/extensions/common/event_matcher.cc
+++ b/extensions/common/event_matcher.cc
@@ -64,20 +64,13 @@
   return 0;
 }
 
-bool EventMatcher::GetURLFilter(int i,
-                                const base::DictionaryValue** url_filter_out) {
+const base::Value::Dict* EventMatcher::GetURLFilter(int i) {
   base::ListValue* url_filters = nullptr;
   if (filter_->GetList(kUrlFiltersKey, &url_filters)) {
     base::Value& dict = url_filters->GetListDeprecated()[i];
-    if (!dict.is_dict()) {
-      return false;
-    }
-    if (url_filter_out) {
-      *url_filter_out = &base::Value::AsDictionaryValue(dict);
-    }
-    return true;
+    return dict.GetIfDict();
   }
-  return false;
+  return nullptr;
 }
 
 bool EventMatcher::HasURLFilters() const {
diff --git a/extensions/common/event_matcher.h b/extensions/common/event_matcher.h
index 7bd54211..141f63cf 100644
--- a/extensions/common/event_matcher.h
+++ b/extensions/common/event_matcher.h
@@ -31,7 +31,7 @@
   bool MatchNonURLCriteria(const mojom::EventFilteringInfo& event_info) const;
 
   int GetURLFilterCount() const;
-  bool GetURLFilter(int i, const base::DictionaryValue** url_filter_out);
+  const base::Value::Dict* GetURLFilter(int i);
 
   int GetWindowTypeCount() const;
   bool GetWindowType(int i, std::string* window_type_out) const;
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ozone.cc b/gpu/command_buffer/service/shared_image_backing_factory_ozone.cc
index b6dc5f44..5f4e07b 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_ozone.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_ozone.cc
@@ -9,6 +9,9 @@
 
 #include "base/logging.h"
 #include "base/memory/scoped_refptr.h"
+#include "build/build_config.h"
+#include "build/chromecast_buildflags.h"
+#include "build/chromeos_buildflags.h"
 #include "components/viz/common/gpu/vulkan_context_provider.h"
 #include "components/viz/common/resources/resource_format_utils.h"
 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
@@ -19,6 +22,7 @@
 #include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gfx/native_pixmap.h"
 #include "ui/gl/buildflags.h"
+#include "ui/gl/gl_surface_egl.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/ozone/public/surface_factory_ozone.h"
 
@@ -196,6 +200,11 @@
     return false;
   }
 
+  if (gmb_type != gfx::EMPTY_BUFFER && gmb_type != gfx::NATIVE_PIXMAP &&
+      gmb_type != gfx::SHARED_MEMORY_BUFFER) {
+    return false;
+  }
+
 #if BUILDFLAG(IS_FUCHSIA)
   DCHECK_EQ(gr_context_type, GrContextType::kVulkan);
 
@@ -209,12 +218,26 @@
       !CanImportGpuMemoryBufferToVulkan(gmb_type)) {
     return false;
   }
-#else
-  if (gmb_type != gfx::EMPTY_BUFFER && gmb_type != gfx::NATIVE_PIXMAP &&
-      gmb_type != gfx::SHARED_MEMORY_BUFFER) {
+#elif BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \
+    !BUILDFLAG(IS_CHROMEOS_LACROS) && !BUILDFLAG(IS_CHROMECAST)
+  bool used_by_skia = (usage & SHARED_IMAGE_USAGE_RASTER) ||
+                      (usage & SHARED_IMAGE_USAGE_DISPLAY);
+  bool used_by_vulkan =
+      used_by_skia && gr_context_type == GrContextType::kVulkan;
+  bool used_by_webgpu = usage & SHARED_IMAGE_USAGE_WEBGPU;
+  bool used_by_gl = (usage & SHARED_IMAGE_USAGE_GLES2) ||
+                    (used_by_skia && gr_context_type == GrContextType::kGL);
+  if (used_by_vulkan && !CanImportGpuMemoryBufferToVulkan(gfx::NATIVE_PIXMAP)) {
     return false;
   }
-
+  if (used_by_webgpu && !CanImportNativePixmapToWebGPU()) {
+    return false;
+  }
+  if (used_by_gl &&
+      !gl::GLSurfaceEGL::GetGLDisplayEGL()->HasEGLExtension("EGL_KHR_image")) {
+    return false;
+  }
+#else
   // TODO(hitawala): Until SharedImageBackingOzone supports all use cases prefer
   // using SharedImageBackingGLImage instead
   bool needs_interop_factory = (gr_context_type == GrContextType::kVulkan &&
@@ -232,6 +255,9 @@
 
 bool SharedImageBackingFactoryOzone::CanImportGpuMemoryBufferToVulkan(
     gfx::GpuMemoryBufferType memory_buffer_type) {
+  if (!shared_context_state_->vk_context_provider()) {
+    return false;
+  }
   auto* vk_device =
       shared_context_state_->vk_context_provider()->GetDeviceQueue();
   return shared_context_state_->vk_context_provider()
@@ -239,4 +265,12 @@
       ->CanImportGpuMemoryBuffer(vk_device, memory_buffer_type);
 }
 
+bool SharedImageBackingFactoryOzone::CanImportNativePixmapToWebGPU() {
+  // Assume that if skia/vulkan vkDevice supports the Vulkan extensions
+  // (external_memory_dma_buf, image_drm_format_modifier), then Dawn/WebGPU also
+  // support the extensions until there is capability to check the extensions
+  // from Dawn vkDevice when they are exposed.
+  return CanImportGpuMemoryBufferToVulkan(gfx::NATIVE_PIXMAP);
+}
+
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ozone.h b/gpu/command_buffer/service/shared_image_backing_factory_ozone.h
index 48a3e82..30cdaba 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_ozone.h
+++ b/gpu/command_buffer/service/shared_image_backing_factory_ozone.h
@@ -73,6 +73,7 @@
  private:
   bool CanImportGpuMemoryBufferToVulkan(
       gfx::GpuMemoryBufferType memory_buffer_type);
+  bool CanImportNativePixmapToWebGPU();
 
   SharedContextState* const shared_context_state_;
   scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs_;
diff --git a/gpu/command_buffer/service/shared_image_backing_shared_memory.cc b/gpu/command_buffer/service/shared_image_backing_shared_memory.cc
index c81f01f..9eb9111 100644
--- a/gpu/command_buffer/service/shared_image_backing_shared_memory.cc
+++ b/gpu/command_buffer/service/shared_image_backing_shared_memory.cc
@@ -29,11 +29,14 @@
   return estimated_size;
 }
 
-SkImageInfo MakeSkImageInfo(const gfx::Size& size, viz::ResourceFormat format) {
+SkImageInfo MakeSkImageInfo(const gfx::Size& size,
+                            viz::ResourceFormat format,
+                            SkAlphaType alpha_type,
+                            const gfx::ColorSpace& color_space) {
   return SkImageInfo::Make(size.width(), size.height(),
                            ResourceFormatToClosestSkColorType(
                                /*gpu_compositing=*/true, format),
-                           kOpaque_SkAlphaType);
+                           alpha_type, color_space.ToSkColorSpace());
 }
 
 class SharedImageRepresentationMemorySharedMemory
@@ -46,8 +49,11 @@
 
  protected:
   SkPixmap BeginReadAccess() override {
-    SkImageInfo info = MakeSkImageInfo(shared_image_shared_memory()->size(),
-                                       shared_image_shared_memory()->format());
+    SkImageInfo info =
+        MakeSkImageInfo(shared_image_shared_memory()->size(),
+                        shared_image_shared_memory()->format(),
+                        shared_image_shared_memory()->alpha_type(),
+                        shared_image_shared_memory()->color_space());
     return SkPixmap(
         info, shared_image_shared_memory()->shared_memory_wrapper().GetMemory(),
         shared_image_shared_memory()->shared_memory_wrapper().GetStride());
diff --git a/gpu/command_buffer/service/shared_image_factory.cc b/gpu/command_buffer/service/shared_image_factory.cc
index 3fedc1fb..e8aec03c 100644
--- a/gpu/command_buffer/service/shared_image_factory.cc
+++ b/gpu/command_buffer/service/shared_image_factory.cc
@@ -53,6 +53,7 @@
 #if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_WIN)) && \
     BUILDFLAG(ENABLE_VULKAN)
 #include "gpu/command_buffer/service/external_vk_image_factory.h"
+#include "gpu/command_buffer/service/shared_image_backing_factory_ozone.h"
 #elif BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_VULKAN)
 #include "gpu/command_buffer/service/external_vk_image_factory.h"
 #include "gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.h"
@@ -380,8 +381,13 @@
 #if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \
     !BUILDFLAG(IS_CHROMEOS_LACROS) && !BUILDFLAG(IS_CHROMECAST)
   // Desktop Linux, not ChromeOS.
+  if (ShouldUseOzoneFactory()) {
+    auto ozone_factory =
+        std::make_unique<SharedImageBackingFactoryOzone>(context_state);
+    factories_.push_back(std::move(ozone_factory));
+  }
   if (gr_context_type_ == GrContextType::kVulkan &&
-      ShouldUseExternalVulkanImageFactory()) {
+      (!ShouldUseOzoneFactory() || ShouldUseExternalVulkanImageFactory())) {
     auto external_vk_image_factory =
         std::make_unique<ExternalVkImageFactory>(context_state);
     factories_.push_back(std::move(external_vk_image_factory));
diff --git a/infra/archive_config/lacros64-archive-rel.json b/infra/archive_config/lacros64-archive-rel.json
new file mode 100644
index 0000000..30e4d1e
--- /dev/null
+++ b/infra/archive_config/lacros64-archive-rel.json
@@ -0,0 +1,55 @@
+{
+   "archive_datas":[
+      {
+         "files":[
+            "chrome.stripped",
+            "chrome_100_percent.pak",
+            "chrome_200_percent.pak",
+            "chrome_crashpad_handler",
+            "headless_lib_data.pak",
+            "headless_lib_strings.pak",
+            "icudtl.dat",
+            "icudtl.dat.hash",
+            "metadata.json",
+            "nacl_helper",
+            "nacl_irt_x86_64.nexe",
+            "resources.pak",
+            "snapshot_blob.bin"
+         ],
+         "file_globs": [
+            "locales/*.pak"
+         ],
+         "rename_files":[
+            {
+               "from_file":"chrome.stripped",
+               "to_file":"chrome"
+            }
+         ],
+         "dirs":[
+            "WidevineCdm"
+         ],
+         "gcs_bucket":"chromium-browser-snapshots",
+         "gcs_path":"lacros64/{%position%}/lacros.zip",
+         "archive_type":"ARCHIVE_TYPE_ZIP"
+      },
+      {
+         "files":[
+            "chrome.debug"
+         ],
+         "dirs": [
+            "locales"
+         ],
+         "gcs_bucket":"chromium-browser-snapshots",
+         "gcs_path":"lacros64/{%position%}/lacros_debug.zip",
+         "archive_type":"ARCHIVE_TYPE_ZIP"
+      },
+      {
+         "files":[
+            "metadata.json"
+         ],
+         "gcs_bucket":"chromium-browser-snapshots",
+         "gcs_path":"lacros64/{%position%}",
+         "archive_type":"ARCHIVE_TYPE_FILES"
+      }
+   ]
+}
diff --git a/infra/config/generated/builders/ci/chromeos-amd64-generic-lacros-dbg/properties.json b/infra/config/generated/builders/ci/chromeos-amd64-generic-lacros-dbg/properties.json
index a2dcb4f..20179b4 100644
--- a/infra/config/generated/builders/ci/chromeos-amd64-generic-lacros-dbg/properties.json
+++ b/infra/config/generated/builders/ci/chromeos-amd64-generic-lacros-dbg/properties.json
@@ -1,9 +1,8 @@
 {
-  "$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": 500,
+    "metrics_project": "chromium-reclient-metrics"
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/lacros64-archive-rel/properties.json b/infra/config/generated/builders/ci/lacros64-archive-rel/properties.json
new file mode 100644
index 0000000..d0a5061
--- /dev/null
+++ b/infra/config/generated/builders/ci/lacros64-archive-rel/properties.json
@@ -0,0 +1,71 @@
+{
+  "$build/archive": {
+    "source_side_spec_path": [
+      "src",
+      "infra",
+      "archive_config",
+      "lacros64-archive-rel.json"
+    ]
+  },
+  "$build/chromium_tests_builder_config": {
+    "builder_config": {
+      "builder_db": {
+        "entries": [
+          {
+            "builder_id": {
+              "bucket": "ci",
+              "builder": "lacros64-archive-rel",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "builder_group": "chromium",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
+                "build_config": "Release",
+                "config": "chromium",
+                "target_arch": "intel",
+                "target_bits": 64,
+                "target_cros_boards": [
+                  "amd64-generic"
+                ],
+                "target_platform": "chromeos"
+              },
+              "legacy_gclient_config": {
+                "apply_configs": [
+                  "chromeos",
+                  "checkout_lacros_sdk"
+                ],
+                "config": "chromium"
+              }
+            }
+          }
+        ]
+      },
+      "builder_ids": [
+        {
+          "bucket": "ci",
+          "builder": "lacros64-archive-rel",
+          "project": "chromium"
+        }
+      ]
+    }
+  },
+  "$build/goma": {
+    "enable_ats": true,
+    "rpc_extra_params": "?prod",
+    "server_host": "goma.chromium.org",
+    "use_luci_auth": true
+  },
+  "$recipe_engine/resultdb/test_presentation": {
+    "column_keys": [],
+    "grouping_keys": [
+      "status",
+      "v.test_suite"
+    ]
+  },
+  "builder_group": "chromium",
+  "recipe": "chromium"
+}
\ No newline at end of file
diff --git a/infra/config/generated/builders/ci/linux-cfm-rel/properties.json b/infra/config/generated/builders/ci/linux-cfm-rel/properties.json
index a2dcb4f..20179b4 100644
--- a/infra/config/generated/builders/ci/linux-cfm-rel/properties.json
+++ b/infra/config/generated/builders/ci/linux-cfm-rel/properties.json
@@ -1,9 +1,8 @@
 {
-  "$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": 500,
+    "metrics_project": "chromium-reclient-metrics"
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/linux-chromeos-annotator-rel/properties.json b/infra/config/generated/builders/ci/linux-chromeos-annotator-rel/properties.json
index fc3bce3..342b501 100644
--- a/infra/config/generated/builders/ci/linux-chromeos-annotator-rel/properties.json
+++ b/infra/config/generated/builders/ci/linux-chromeos-annotator-rel/properties.json
@@ -1,9 +1,8 @@
 {
-  "$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": 500,
+    "metrics_project": "chromium-reclient-metrics"
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/linux-chromeos-code-coverage/properties.json b/infra/config/generated/builders/ci/linux-chromeos-code-coverage/properties.json
index 573155d..886262c 100644
--- a/infra/config/generated/builders/ci/linux-chromeos-code-coverage/properties.json
+++ b/infra/config/generated/builders/ci/linux-chromeos-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": 500,
+    "metrics_project": "chromium-reclient-metrics"
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/linux-chromeos-dbg/properties.json b/infra/config/generated/builders/ci/linux-chromeos-dbg/properties.json
index a2dcb4f..20179b4 100644
--- a/infra/config/generated/builders/ci/linux-chromeos-dbg/properties.json
+++ b/infra/config/generated/builders/ci/linux-chromeos-dbg/properties.json
@@ -1,9 +1,8 @@
 {
-  "$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": 500,
+    "metrics_project": "chromium-reclient-metrics"
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 7c8bdd8..c51f0c5 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -32580,6 +32580,85 @@
       }
     }
     builders {
+      name: "lacros64-archive-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "builderless:1"
+      dimensions: "cores:32"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/ci/lacros64-archive-rel/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "chromium",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium"'
+        '}'
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://[^/]*blink_web_tests/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "linux-angle-builder"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index bd794cf1..5985272 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -31,6 +31,11 @@
     short_name: "off"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/lacros64-archive-rel"
+    category: "chromium|lacros"
+    short_name: "rel"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/linux-archive-dbg"
     category: "chromium|linux"
     short_name: "dbg"
@@ -2723,6 +2728,11 @@
     short_name: "off"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/lacros64-archive-rel"
+    category: "lacros"
+    short_name: "rel"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/linux-archive-dbg"
     category: "linux"
     short_name: "dbg"
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg
index 0906c6e..9246cb2 100644
--- a/infra/config/generated/luci/luci-scheduler.cfg
+++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -5485,6 +5485,16 @@
   }
 }
 job {
+  id: "lacros64-archive-rel"
+  realm: "ci"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "ci"
+    builder: "lacros64-archive-rel"
+  }
+}
+job {
   id: "linux-angle-builder"
   realm: "ci"
   acl_sets: "ci"
@@ -7400,6 +7410,7 @@
   triggers: "lacros-amd64-generic-rel-fyi"
   triggers: "lacros-amd64-generic-rel-skylab-fyi"
   triggers: "lacros-arm-generic-rel"
+  triggers: "lacros64-archive-rel"
   triggers: "linux-angle-builder"
   triggers: "linux-angle-chromium-builder"
   triggers: "linux-annotator-rel"
diff --git a/infra/config/generated/luci/project.cfg b/infra/config/generated/luci/project.cfg
index 5682f3ad..5d4b8b8 100644
--- a/infra/config/generated/luci/project.cfg
+++ b/infra/config/generated/luci/project.cfg
@@ -7,7 +7,7 @@
 name: "chromium"
 access: "group:all"
 lucicfg {
-  version: "1.30.10"
+  version: "1.30.11"
   package_dir: "../.."
   config_dir: "generated/luci"
   entry_point: "main.star"
diff --git a/infra/config/subprojects/chromium/ci/chromium.chromiumos.star b/infra/config/subprojects/chromium/ci/chromium.chromiumos.star
index 31aa44f..f5d57519 100644
--- a/infra/config/subprojects/chromium/ci/chromium.chromiumos.star
+++ b/infra/config/subprojects/chromium/ci/chromium.chromiumos.star
@@ -249,6 +249,9 @@
     ),
     cq_mirrors_console_view = "mirrors",
     main_console_view = "main",
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.HIGH_JOBS_FOR_CI,
+    reclient_instance = rbe_instance.DEFAULT,
 )
 
 ci.builder(
@@ -527,6 +530,9 @@
     ),
     cq_mirrors_console_view = "mirrors",
     main_console_view = "main",
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.HIGH_JOBS_FOR_CI,
+    reclient_instance = rbe_instance.DEFAULT,
 )
 
 ci.builder(
@@ -586,4 +592,7 @@
         short_name = "cfm",
     ),
     main_console_view = "main",
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.HIGH_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 edd0a21..a128c920 100644
--- a/infra/config/subprojects/chromium/ci/chromium.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -351,7 +351,9 @@
     ),
     execution_timeout = 3 * time.hour,
     os = os.LINUX_BIONIC_SWITCH_TO_DEFAULT,
-    goma_enable_ats = True,
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.HIGH_JOBS_FOR_CI,
+    reclient_instance = rbe_instance.DEFAULT,
 )
 
 ci.builder(
@@ -1161,6 +1163,9 @@
     coverage_test_types = ["overall", "unit"],
     schedule = "triggered",
     triggered_by = [],
+    goma_backend = None,
+    reclient_jobs = rbe_jobs.HIGH_JOBS_FOR_CI,
+    reclient_instance = rbe_instance.DEFAULT,
 )
 
 fyi_coverage_builder(
diff --git a/infra/config/subprojects/chromium/ci/chromium.star b/infra/config/subprojects/chromium/ci/chromium.star
index 385145a..6101ae81 100644
--- a/infra/config/subprojects/chromium/ci/chromium.star
+++ b/infra/config/subprojects/chromium/ci/chromium.star
@@ -4,6 +4,7 @@
 """Definitions of builders in the chromium builder group."""
 
 load("//lib/args.star", "args")
+load("//lib/builder_config.star", "builder_config")
 load("//lib/builders.star", "goma", "os", "sheriff_rotations")
 load("//lib/branches.star", "branches")
 load("//lib/ci.star", "ci", "rbe_instance", "rbe_jobs")
@@ -122,6 +123,53 @@
 )
 
 ci.builder(
+    name = "lacros64-archive-rel",
+    console_view_entry = consoles.console_view_entry(
+        category = "lacros",
+        short_name = "rel",
+    ),
+    branch_selector = branches.STANDARD_MILESTONE,
+    builder_spec = builder_config.builder_spec(
+        gclient_config = builder_config.gclient_config(
+            config = "chromium",
+            apply_configs = [
+                "chromeos",
+                "checkout_lacros_sdk",
+            ],
+        ),
+        chromium_config = builder_config.chromium_config(
+            config = "chromium",
+            apply_configs = [
+                "mb",
+            ],
+            build_config = builder_config.build_config.RELEASE,
+            target_arch = builder_config.target_arch.INTEL,
+            target_bits = 64,
+            target_cros_boards = [
+                "amd64-generic",
+            ],
+            target_platform = builder_config.target_platform.CHROMEOS,
+        ),
+    ),
+    cores = 32,
+    os = os.LINUX_BIONIC_REMOVE,
+    properties = {
+        # The format of these properties is defined at archive/properties.proto
+        "$build/archive": {
+            "source_side_spec_path": [
+                "src",
+                "infra",
+                "archive_config",
+                "lacros64-archive-rel.json",
+            ],
+        },
+    },
+    # TODO(crbug.com/1320042): Turn on after it's stable.
+    tree_closing = False,
+    sheriff_rotations = args.ignore_default(None),
+)
+
+ci.builder(
     name = "linux-archive-dbg",
     console_view_entry = consoles.console_view_entry(
         category = "linux",
diff --git a/ios/chrome/browser/follow/BUILD.gn b/ios/chrome/browser/follow/BUILD.gn
index 3a8de1d..376b3be 100644
--- a/ios/chrome/browser/follow/BUILD.gn
+++ b/ios/chrome/browser/follow/BUILD.gn
@@ -20,6 +20,19 @@
   configs += [ "//build/config/compiler:enable_arc" ]
 }
 
+source_set("tab_helper") {
+  sources = [
+    "follow_tab_helper.h",
+    "follow_tab_helper.mm",
+  ]
+  deps = [
+    "//base",
+    "//ios/chrome/browser/browser_state",
+    "//ios/web/public",
+  ]
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
 optimize_js("rss_link_js") {
   visibility = [ ":follow" ]
 
diff --git a/ios/chrome/browser/follow/follow_tab_helper.h b/ios/chrome/browser/follow/follow_tab_helper.h
new file mode 100644
index 0000000..66ba426
--- /dev/null
+++ b/ios/chrome/browser/follow/follow_tab_helper.h
@@ -0,0 +1,54 @@
+// 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 IOS_CHROME_BROWSER_FOLLOW_FOLLOW_TAB_HELPER_H_
+#define IOS_CHROME_BROWSER_FOLLOW_FOLLOW_TAB_HELPER_H_
+
+#import <UIKit/UIKit.h>
+
+#include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
+#include "ios/web/public/web_state_observer.h"
+#import "ios/web/public/web_state_user_data.h"
+
+namespace web {
+class WebState;
+}
+
+// FollowTabHelper encapsulates tab behavior related to following channels.
+class FollowTabHelper : public web::WebStateObserver,
+                        public web::WebStateUserData<FollowTabHelper> {
+ public:
+  FollowTabHelper(const FollowTabHelper&) = delete;
+  FollowTabHelper& operator=(const FollowTabHelper&) = delete;
+
+  ~FollowTabHelper() override;
+
+  // Creates the TabHelper and attaches to |web_state|. |web_state| must not be
+  // null.
+  static void CreateForWebState(web::WebState* web_state);
+
+ private:
+  friend class web::WebStateUserData<FollowTabHelper>;
+
+  explicit FollowTabHelper(web::WebState* web_state);
+
+  // web::WebStateObserver implementation.
+  void PageLoaded(
+      web::WebState* web_state,
+      web::PageLoadCompletionStatus load_completion_status) override;
+  void WebStateDestroyed(web::WebState* web_state) override;
+
+  web::WebState* web_state_ = nullptr;
+
+  // Manages this object as an observer of |web_state_|.
+  base::ScopedObservation<web::WebState, web::WebStateObserver>
+      web_state_observation_{this};
+
+  base::WeakPtrFactory<FollowTabHelper> weak_ptr_factory_;
+
+  WEB_STATE_USER_DATA_KEY_DECL();
+};
+
+#endif  // IOS_CHROME_BROWSER_FOLLOW_FOLLOW_TAB_HELPER_H_
diff --git a/ios/chrome/browser/follow/follow_tab_helper.mm b/ios/chrome/browser/follow/follow_tab_helper.mm
new file mode 100644
index 0000000..5037f351
--- /dev/null
+++ b/ios/chrome/browser/follow/follow_tab_helper.mm
@@ -0,0 +1,54 @@
+// 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.
+
+#import "ios/chrome/browser/follow/follow_tab_helper.h"
+
+#include "base/memory/ptr_util.h"
+#import "ios/web/public/web_state.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+FollowTabHelper::~FollowTabHelper() {
+  DCHECK(!web_state_);
+}
+
+// static
+void FollowTabHelper::CreateForWebState(web::WebState* web_state) {
+  DCHECK(web_state);
+  if (!FromWebState(web_state)) {
+    web_state->SetUserData(UserDataKey(),
+                           base::WrapUnique(new FollowTabHelper(web_state)));
+  }
+}
+
+FollowTabHelper::FollowTabHelper(web::WebState* web_state)
+    : web_state_(web_state), weak_ptr_factory_(this) {
+  DCHECK(web_state_);
+  web_state_observation_.Observe(web_state_);
+}
+
+void FollowTabHelper::PageLoaded(
+    web::WebState* web_state,
+    web::PageLoadCompletionStatus load_completion_status) {
+  switch (load_completion_status) {
+    case web::PageLoadCompletionStatus::FAILURE:
+      break;
+    case web::PageLoadCompletionStatus::SUCCESS:
+      // TODO(crbug.com/1318755): Get recommended status from follow provider.
+      // If recommended, use feature engagement tracker to decide whether to
+      // show the while-browsing IPH.
+      break;
+  }
+}
+
+void FollowTabHelper::WebStateDestroyed(web::WebState* web_state) {
+  DCHECK_EQ(web_state_, web_state);
+  DCHECK(web_state_observation_.IsObservingSource(web_state));
+  web_state_observation_.Reset();
+  web_state_ = nullptr;
+}
+
+WEB_STATE_USER_DATA_KEY_IMPL(FollowTabHelper)
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn
index 4bda9a21..9c127c1 100644
--- a/ios/chrome/browser/tabs/BUILD.gn
+++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -63,6 +63,7 @@
     "//ios/chrome/browser/download",
     "//ios/chrome/browser/favicon",
     "//ios/chrome/browser/find_in_page",
+    "//ios/chrome/browser/follow:tab_helper",
     "//ios/chrome/browser/geolocation",
     "//ios/chrome/browser/history",
     "//ios/chrome/browser/history:tab_helper",
@@ -75,6 +76,7 @@
     "//ios/chrome/browser/main",
     "//ios/chrome/browser/metrics",
     "//ios/chrome/browser/ntp",
+    "//ios/chrome/browser/ntp:features",
     "//ios/chrome/browser/open_in",
     "//ios/chrome/browser/optimization_guide",
     "//ios/chrome/browser/overscroll_actions",
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm
index 4dacb3fa..3bce4ca 100644
--- a/ios/chrome/browser/tabs/tab_helper_util.mm
+++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -35,6 +35,7 @@
 #import "ios/chrome/browser/download/vcard_tab_helper.h"
 #include "ios/chrome/browser/favicon/favicon_service_factory.h"
 #import "ios/chrome/browser/find_in_page/find_tab_helper.h"
+#import "ios/chrome/browser/follow/follow_tab_helper.h"
 #include "ios/chrome/browser/history/history_service_factory.h"
 #include "ios/chrome/browser/history/history_tab_helper.h"
 #include "ios/chrome/browser/history/top_sites_factory.h"
@@ -48,6 +49,7 @@
 #import "ios/chrome/browser/language/url_language_histogram_factory.h"
 #import "ios/chrome/browser/link_to_text/link_to_text_tab_helper.h"
 #import "ios/chrome/browser/metrics/pageload_foreground_duration_tab_helper.h"
+#import "ios/chrome/browser/ntp/features.h"
 #import "ios/chrome/browser/ntp/new_tab_page_tab_helper.h"
 #import "ios/chrome/browser/open_in/open_in_tab_helper.h"
 #import "ios/chrome/browser/optimization_guide/optimization_guide_tab_helper.h"
@@ -241,4 +243,8 @@
     HttpsOnlyModeContainer::CreateForWebState(web_state);
     HttpsOnlyModeAllowlist::CreateForWebState(web_state);
   }
+
+  if (IsWebChannelsEnabled()) {
+    FollowTabHelper::CreateForWebState(web_state);
+  }
 }
diff --git a/ios/web/download/data_url_download_task.mm b/ios/web/download/data_url_download_task.mm
index 7bbb406..46a630ed 100644
--- a/ios/web/download/data_url_download_task.mm
+++ b/ios/web/download/data_url_download_task.mm
@@ -9,7 +9,6 @@
 #import "base/files/file_util.h"
 #import "base/logging.h"
 #import "base/strings/sys_string_conversions.h"
-#import "base/task/post_task.h"
 #import "base/task/task_traits.h"
 #import "base/task/thread_pool.h"
 #import "ios/web/download/download_result.h"
diff --git a/media/audio/cras/audio_manager_chromeos_unittest.cc b/media/audio/cras/audio_manager_chromeos_unittest.cc
index d860cfac..440f790e 100644
--- a/media/audio/cras/audio_manager_chromeos_unittest.cc
+++ b/media/audio/cras/audio_manager_chromeos_unittest.cc
@@ -4,6 +4,7 @@
 #include "media/audio/cras/audio_manager_chromeos.h"
 
 #include "base/test/scoped_feature_list.h"
+#include "build/chromeos_buildflags.h"
 #include "media/audio/audio_features.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/media/base/android/BUILD.gn b/media/base/android/BUILD.gn
index 54375dd..ebe32e2 100644
--- a/media/base/android/BUILD.gn
+++ b/media/base/android/BUILD.gn
@@ -164,6 +164,7 @@
       ":display_java",
       ":media_java_resources",
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
     ]
     annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/media/base/decoder_status.cc b/media/base/decoder_status.cc
index 44d0aaf1..299653c 100644
--- a/media/base/decoder_status.cc
+++ b/media/base/decoder_status.cc
@@ -40,6 +40,7 @@
     STRINGIFY(DecoderStatus::Codes::kFailedToCreateDecoder);
     STRINGIFY(DecoderStatus::Codes::kKeyFrameRequired);
     STRINGIFY(DecoderStatus::Codes::kMissingTimestamp);
+    STRINGIFY(DecoderStatus::Codes::kTooManyDecoders);
   }
 #undef STRINGIFY
 }
diff --git a/media/base/decoder_status.h b/media/base/decoder_status.h
index dd2a0c65..bc2f87d4 100644
--- a/media/base/decoder_status.h
+++ b/media/base/decoder_status.h
@@ -40,6 +40,7 @@
     kUnsupportedEncryptionMode = 203,
     kCantChangeCodec = 204,
     kFailedToCreateDecoder = 205,
+    kTooManyDecoders = 206,
   };
   static constexpr StatusGroupType Group() { return "DecoderStatus"; }
   static constexpr Codes DefaultEnumValue() { return Codes::kOk; }
diff --git a/media/capture/content/android/BUILD.gn b/media/capture/content/android/BUILD.gn
index e73ae45c..fd07801 100644
--- a/media/capture/content/android/BUILD.gn
+++ b/media/capture/content/android/BUILD.gn
@@ -36,6 +36,7 @@
 android_library("screen_capture_java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
   sources = [ "java/src/org/chromium/media/ScreenCapture.java" ]
diff --git a/media/capture/video/android/BUILD.gn b/media/capture/video/android/BUILD.gn
index 6ffcf8e8..23e6337c 100644
--- a/media/capture/video/android/BUILD.gn
+++ b/media/capture/video/android/BUILD.gn
@@ -51,6 +51,7 @@
 android_library("capture_java") {
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc
index b2d986b7..f2c4650 100644
--- a/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc
+++ b/media/gpu/vaapi/av1_vaapi_video_decoder_delegate.cc
@@ -12,6 +12,7 @@
 #include "base/callback_helpers.h"
 #include "base/logging.h"
 #include "base/memory/scoped_refptr.h"
+#include "build/chromeos_buildflags.h"
 #include "media/gpu/av1_picture.h"
 #include "media/gpu/decode_surface_handler.h"
 #include "media/gpu/vaapi/vaapi_common.h"
diff --git a/media/gpu/vaapi/test/decode.cc b/media/gpu/vaapi/test/decode.cc
index 35723fd..526405b 100644
--- a/media/gpu/vaapi/test/decode.cc
+++ b/media/gpu/vaapi/test/decode.cc
@@ -14,6 +14,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "build/chromeos_buildflags.h"
 #include "media/filters/ivf_parser.h"
 #include "media/gpu/vaapi/test/av1_decoder.h"
 #include "media/gpu/vaapi/test/shared_va_surface.h"
diff --git a/media/gpu/vaapi/vaapi_image_processor_backend.cc b/media/gpu/vaapi/vaapi_image_processor_backend.cc
index 72f49658..6c8cd3d 100644
--- a/media/gpu/vaapi/vaapi_image_processor_backend.cc
+++ b/media/gpu/vaapi/vaapi_image_processor_backend.cc
@@ -16,6 +16,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/stl_util.h"
 #include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
 #include "media/gpu/chromeos/fourcc.h"
 #include "media/gpu/chromeos/platform_video_frame_utils.h"
 #include "media/gpu/macros.h"
diff --git a/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc b/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
index b4b78925..546fe5a 100644
--- a/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
+++ b/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/run_loop.h"
 #include "base/test/gmock_callback_support.h"
 #include "base/test/task_environment.h"
+#include "build/chromeos_buildflags.h"
 #include "media/base/media_util.h"
 #include "media/gpu/gpu_video_encode_accelerator_helpers.h"
 #include "media/gpu/vaapi/vaapi_utils.h"
diff --git a/media/midi/BUILD.gn b/media/midi/BUILD.gn
index abefcea3..9e9aef0 100644
--- a/media/midi/BUILD.gn
+++ b/media/midi/BUILD.gn
@@ -50,6 +50,7 @@
   android_library("midi_java") {
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
     ]
     annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/media/mojo/services/mojo_video_decoder_service.cc b/media/mojo/services/mojo_video_decoder_service.cc
index 4369bc4..650bee0 100644
--- a/media/mojo/services/mojo_video_decoder_service.cc
+++ b/media/mojo/services/mojo_video_decoder_service.cc
@@ -196,6 +196,15 @@
 
   init_cb_ = std::move(callback);
 
+  // Prevent creation of too many hardware decoding instances since it may lead
+  // to system instability. Note: This will break decoding entirely for codecs
+  // which don't have software fallback, so we use a conservative limit. Most
+  // platforms will self-limit and never reach this limit.
+  if (!config.is_encrypted() && g_num_active_mvd_instances >= 128) {
+    OnDecoderInitialized(DecoderStatus::Codes::kTooManyDecoders);
+    return;
+  }
+
   if (!decoder_) {
     OnDecoderInitialized(DecoderStatus::Codes::kFailedToCreateDecoder);
     return;
diff --git a/mojo/public/java/system/BUILD.gn b/mojo/public/java/system/BUILD.gn
index daec5ec..8fb3cc3 100644
--- a/mojo/public/java/system/BUILD.gn
+++ b/mojo/public/java/system/BUILD.gn
@@ -60,6 +60,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//mojo/public/java:system_java",
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
@@ -119,6 +120,7 @@
     ":test_support_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//mojo/public/interfaces/bindings/tests:test_interfaces_java",
     "//mojo/public/interfaces/bindings/tests:test_mojom_import2_java",
     "//mojo/public/interfaces/bindings/tests:test_mojom_import_java",
@@ -163,6 +165,7 @@
     ":mojo_javatests",
     ":system_impl_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//mojo/public/interfaces/bindings/tests:test_interfaces",
     "//mojo/public/java:bindings_java",
     "//third_party/androidx:androidx_test_monitor_java",
diff --git a/net/android/BUILD.gn b/net/android/BUILD.gn
index dc4759c..ccd921ba 100644
--- a/net/android/BUILD.gn
+++ b/net/android/BUILD.gn
@@ -32,6 +32,7 @@
   deps = [
     ":net_thread_stats_uid_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/android_deps:com_google_code_findbugs_jsr305_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
@@ -101,6 +102,7 @@
     ":net_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
   ]
 
   data_deps = [ "//net:test_support" ]
@@ -148,6 +150,7 @@
     ":net_java_test_support",
     ":net_java_test_support_provider",
     "//base:base_java",
+    "//build/android:build_java",
   ]
   android_manifest = "../test/android/javatests/AndroidManifest.xml"
   apk_name = "ChromiumNetTestSupport"
@@ -187,6 +190,7 @@
     ":net_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//third_party/android_sdk:android_test_mock_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
@@ -229,6 +233,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//third_party/hamcrest:hamcrest_java",
   ]
 }
diff --git a/net/der/encode_values_unittest.cc b/net/der/encode_values_unittest.cc
index ed929a8..1a089ff 100644
--- a/net/der/encode_values_unittest.cc
+++ b/net/der/encode_values_unittest.cc
@@ -47,13 +47,9 @@
 // on platforms where it returns true. As of this writing, it will return false
 // on Windows.
 TEST(EncodeValuesTest, EncodeTimeFromBeforeWindowsEpoch) {
-  constexpr int kYearsBeforeWindowsEpoch = 1601 - 1570;
-  constexpr int kDaysPerYear = 365;
-  constexpr int kExtraLeapDaysOverThoseYears = 8;
+  // Thu, 01 Jan 1570 00:00:00 GMT
   constexpr base::Time kStartOfYear1570 =
-      base::Time() - base::Days(kYearsBeforeWindowsEpoch * kDaysPerYear +
-                                kExtraLeapDaysOverThoseYears);
-
+      base::Time::UnixEpoch() - base::Seconds(12622780800);
   GeneralizedTime generalized_time;
   if (!EncodeTimeAsGeneralizedTime(kStartOfYear1570, &generalized_time))
     return;
diff --git a/pdf/paint_manager.cc b/pdf/paint_manager.cc
index c6d4d46b..118524f 100644
--- a/pdf/paint_manager.cc
+++ b/pdf/paint_manager.cc
@@ -189,7 +189,12 @@
     gfx::Size old_size = graphics_ ? graphics_->size() : gfx::Size();
     gfx::Size new_size = GetNewContextSize(old_size, pending_size_);
     if (old_size != new_size || !graphics_) {
-      graphics_ = client_->CreatePaintGraphics(new_size);
+      graphics_ = SkiaGraphics::Create(client_, new_size);
+      DCHECK(graphics_);
+
+      // TODO(crbug.com/1317832): Can we guarantee repainting some other way?
+      client_->InvalidatePluginContainer();
+
       device_scale_ = 1.0f;
 
       // Since we're binding a new one, all of the callbacks have been canceled.
diff --git a/pdf/paint_manager.h b/pdf/paint_manager.h
index 868a4dc..6e757bc 100644
--- a/pdf/paint_manager.h
+++ b/pdf/paint_manager.h
@@ -14,6 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "pdf/paint_aggregator.h"
+#include "pdf/ppapi_migration/graphics.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace gfx {
@@ -24,8 +25,6 @@
 
 namespace chrome_pdf {
 
-class Graphics;
-
 // Custom PaintManager for the PDF plugin.  This is branched from the Pepper
 // version.  The difference is that this supports progressive rendering of dirty
 // rects, where multiple calls to the rendering engine are needed.  It also
@@ -35,12 +34,10 @@
 // The client's OnPaint
 class PaintManager {
  public:
-  class Client {
+  class Client : public SkiaGraphics::Client {
    public:
-    // Creates a new `Graphics` for the paint manager, with the given `size` and
-    // always-opaque rendering.
-    virtual std::unique_ptr<Graphics> CreatePaintGraphics(
-        const gfx::Size& size) = 0;
+    // Invalidates the entire plugin container, scheduling a repaint.
+    virtual void InvalidatePluginContainer() = 0;
 
     // Paints the given invalid area of the plugin to the given graphics
     // device. Returns true if anything was painted.
@@ -65,8 +62,8 @@
                          std::vector<gfx::Rect>& pending) = 0;
 
    protected:
-    // You shouldn't be doing deleting through this interface.
-    ~Client() = default;
+    // You shouldn't delete through this interface.
+    ~Client() override = default;
   };
 
   // The Client is a non-owning pointer and must remain valid (normally the
diff --git a/pdf/paint_manager_unittest.cc b/pdf/paint_manager_unittest.cc
index 89e8ba7..3516420 100644
--- a/pdf/paint_manager_unittest.cc
+++ b/pdf/paint_manager_unittest.cc
@@ -32,21 +32,15 @@
       .AppendASCII(filename);
 }
 
-class FakeClient : public PaintManager::Client, public SkiaGraphics::Client {
+class FakeClient : public PaintManager::Client {
  public:
-  // `PaintManager::Client`:
-  MOCK_METHOD(std::unique_ptr<Graphics>,
-              CreatePaintGraphics,
-              (const gfx::Size& size),
-              (override));
+  MOCK_METHOD(void, InvalidatePluginContainer, (), (override));
   MOCK_METHOD(void,
               OnPaint,
               (const std::vector<gfx::Rect>& paint_rects,
                std::vector<PaintReadyRect>& ready,
                std::vector<gfx::Rect>& pending),
               (override));
-
-  // `SkiaGraphics::Client`:
   MOCK_METHOD(void, UpdateSnapshot, (sk_sp<SkImage> snapshot), (override));
   MOCK_METHOD(void, UpdateScale, (float scale), (override));
   MOCK_METHOD(void,
@@ -57,13 +51,6 @@
 
 class PaintManagerTest : public testing::Test {
  protected:
-  void SetUp() override {
-    ON_CALL(client_, CreatePaintGraphics)
-        .WillByDefault([this](const gfx::Size& size) {
-          return SkiaGraphics::Create(&client_, size);
-        });
-  }
-
   void WaitForOnPaint() {
     base::RunLoop run_loop;
     EXPECT_CALL(client_, OnPaint).WillOnce([&run_loop] { run_loop.Quit(); });
@@ -133,7 +120,7 @@
 }
 
 TEST_F(PaintManagerTest, SetSizeWithoutPaint) {
-  EXPECT_CALL(client_, CreatePaintGraphics).Times(0);
+  EXPECT_CALL(client_, InvalidatePluginContainer).Times(0);
   paint_manager_.SetSize({400, 300}, 2.0f);
 
   EXPECT_EQ(gfx::Size(400, 300), paint_manager_.GetEffectiveSize());
@@ -143,7 +130,7 @@
 TEST_F(PaintManagerTest, SetSizeWithPaint) {
   paint_manager_.SetSize({400, 300}, 2.0f);
 
-  EXPECT_CALL(client_, CreatePaintGraphics(gfx::Size(450, 350)));
+  EXPECT_CALL(client_, InvalidatePluginContainer);
   EXPECT_CALL(client_, UpdateScale(0.5f));
   WaitForOnPaint();
 }
diff --git a/pdf/pdf_view_plugin_base_unittest.cc b/pdf/pdf_view_plugin_base_unittest.cc
index 2516ba54..1a27a84b 100644
--- a/pdf/pdf_view_plugin_base_unittest.cc
+++ b/pdf/pdf_view_plugin_base_unittest.cc
@@ -119,9 +119,12 @@
 
   MOCK_METHOD(bool, IsValidLink, (const std::string&), (override));
 
-  MOCK_METHOD(std::unique_ptr<Graphics>,
-              CreatePaintGraphics,
-              (const gfx::Size&),
+  MOCK_METHOD(void, InvalidatePluginContainer, (), (override));
+  MOCK_METHOD(void, UpdateSnapshot, (sk_sp<SkImage>), (override));
+  MOCK_METHOD(void, UpdateScale, (float), (override));
+  MOCK_METHOD(void,
+              UpdateLayerTransform,
+              (float, const gfx::Vector2dF&),
               (override));
 
   MOCK_METHOD(std::unique_ptr<PDFiumEngine>,
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc
index 1033a28..873e6db3 100644
--- a/pdf/pdf_view_web_plugin.cc
+++ b/pdf/pdf_view_web_plugin.cc
@@ -43,7 +43,6 @@
 #include "pdf/post_message_receiver.h"
 #include "pdf/post_message_sender.h"
 #include "pdf/ppapi_migration/bitmap.h"
-#include "pdf/ppapi_migration/graphics.h"
 #include "pdf/ppapi_migration/result_codes.h"
 #include "pdf/ppapi_migration/url_loader.h"
 #include "pdf/ui/document_properties.h"
@@ -821,19 +820,6 @@
   return base::Value(url).is_string();
 }
 
-std::unique_ptr<Graphics> PdfViewWebPlugin::CreatePaintGraphics(
-    const gfx::Size& size) {
-  // `this` must be valid when creating new graphics. `this` is guaranteed to
-  // outlive `graphics`; the implemented client interface owns the paint manager
-  // in which the graphics device exists.
-  auto graphics = SkiaGraphics::Create(this, size);
-  DCHECK(graphics);
-
-  // TODO(crbug.com/1317832): Can we guarantee repainting some other way?
-  InvalidatePluginContainer();
-  return graphics;
-}
-
 void PdfViewWebPlugin::SetCaretPosition(const gfx::PointF& position) {
   PdfViewPluginBase::SetCaretPosition(position);
 }
@@ -878,6 +864,10 @@
   PdfViewPluginBase::HandleMessage(message);
 }
 
+void PdfViewWebPlugin::InvalidatePluginContainer() {
+  container_wrapper_->Invalidate();
+}
+
 void PdfViewWebPlugin::UpdateSnapshot(sk_sp<SkImage> snapshot) {
   snapshot_ =
       cc::PaintImageBuilder::WithDefault()
@@ -1060,10 +1050,6 @@
   UpdateGeometryOnPluginRectChanged(plugin_rect_in_css_pixel, new_device_scale);
 }
 
-void PdfViewWebPlugin::InvalidatePluginContainer() {
-  container_wrapper_->Invalidate();
-}
-
 bool PdfViewWebPlugin::SelectAll() {
   if (!CanEditText())
     return false;
diff --git a/pdf/pdf_view_web_plugin.h b/pdf/pdf_view_web_plugin.h
index c0682c1..23ec046 100644
--- a/pdf/pdf_view_web_plugin.h
+++ b/pdf/pdf_view_web_plugin.h
@@ -20,7 +20,6 @@
 #include "pdf/pdf_accessibility_action_handler.h"
 #include "pdf/pdf_view_plugin_base.h"
 #include "pdf/post_message_receiver.h"
-#include "pdf/ppapi_migration/graphics.h"
 #include "pdf/ppapi_migration/url_loader.h"
 #include "pdf/v8_value_converter.h"
 #include "third_party/blink/public/platform/web_string.h"
@@ -62,7 +61,6 @@
                                public pdf::mojom::PdfListener,
                                public BlinkUrlLoader::Client,
                                public PostMessageReceiver::Client,
-                               public SkiaGraphics::Client,
                                public PdfAccessibilityActionHandler {
  public:
   class ContainerWrapper {
@@ -253,9 +251,6 @@
   void SetSelectedText(const std::string& selected_text) override;
   bool IsValidLink(const std::string& url) override;
 
-  // PdfViewPluginBase:
-  std::unique_ptr<Graphics> CreatePaintGraphics(const gfx::Size& size) override;
-
   // pdf::mojom::PdfListener:
   void SetCaretPosition(const gfx::PointF& position) override;
   void MoveRangeSelectionExtent(const gfx::PointF& extent) override;
@@ -274,7 +269,8 @@
   // PostMessageReceiver::Client:
   void OnMessage(const base::Value::Dict& message) override;
 
-  // SkiaGraphics::Client:
+  // PaintManager::Client:
+  void InvalidatePluginContainer() override;
   void UpdateSnapshot(sk_sp<SkImage> snapshot) override;
   void UpdateScale(float scale) override;
   void UpdateLayerTransform(float scale,
@@ -342,10 +338,6 @@
   void OnViewportChanged(const gfx::Rect& plugin_rect_in_css_pixel,
                          float new_device_scale);
 
-  // Invalidates the entire web plugin container and schedules a paint of the
-  // page in it.
-  void InvalidatePluginContainer();
-
   // Text editing methods.
   bool SelectAll();
   bool Cut();
diff --git a/pdf/pdf_view_web_plugin_unittest.cc b/pdf/pdf_view_web_plugin_unittest.cc
index 8e54e842..08ed5eed 100644
--- a/pdf/pdf_view_web_plugin_unittest.cc
+++ b/pdf/pdf_view_web_plugin_unittest.cc
@@ -424,16 +424,11 @@
     UpdatePluginGeometry(device_scale, window_rect);
     canvas_.DrawColor(kDefaultColor);
 
-    // Fill the graphics device with `kPaintColor` and update the plugin's
-    // snapshot.
-    const gfx::Rect& plugin_rect = plugin_->GetPluginRectForTesting();
-    std::unique_ptr<Graphics> graphics =
-        plugin_->CreatePaintGraphics(plugin_rect.size());
-    graphics->PaintImage(
-        CreateSkiaImageForTesting(plugin_rect.size(), kPaintColor),
-        gfx::Rect(plugin_rect.width(), plugin_rect.height()));
-    graphics->Flush(base::DoNothing());
-
+    // Paint the plugin with `kPaintColor`.
+    plugin_->UpdateSnapshot(
+        CreateSkiaImageForTesting(plugin_->GetPluginRectForTesting().size(),
+                                  kPaintColor)
+            .asImage());
     plugin_->Paint(canvas_.sk_canvas(), paint_rect);
 
     // Expect the clipped area on canvas to be filled with `kPaintColor`.
diff --git a/printing/BUILD.gn b/printing/BUILD.gn
index 83350a5..22c03cda 100644
--- a/printing/BUILD.gn
+++ b/printing/BUILD.gn
@@ -416,6 +416,7 @@
   android_library("printing_java") {
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
       "//ui/android:ui_java",
     ]
diff --git a/printing/printing_features.cc b/printing/printing_features.cc
index f19ed5a..0091fb1 100644
--- a/printing/printing_features.cc
+++ b/printing/printing_features.cc
@@ -65,6 +65,9 @@
 
 const base::FeatureParam<bool> kEnableOopPrintDriversJobPrint{
     &kEnableOopPrintDrivers, "JobPrint", false};
+
+const base::FeatureParam<bool> kEnableOopPrintDriversSandbox{
+    &kEnableOopPrintDrivers, "Sandbox", false};
 #endif  // BUILDFLAG(ENABLE_OOP_PRINTING)
 
 #if BUILDFLAG(ENABLE_PRINT_CONTENT_ANALYSIS)
diff --git a/printing/printing_features.h b/printing/printing_features.h
index 2159bc1..6cdcd4ec 100644
--- a/printing/printing_features.h
+++ b/printing/printing_features.h
@@ -49,6 +49,8 @@
 extern const base::Feature kEnableOopPrintDrivers;
 COMPONENT_EXPORT(PRINTING_BASE)
 extern const base::FeatureParam<bool> kEnableOopPrintDriversJobPrint;
+COMPONENT_EXPORT(PRINTING_BASE)
+extern const base::FeatureParam<bool> kEnableOopPrintDriversSandbox;
 #endif  // BUILDFLAG(ENABLE_OOP_PRINTING)
 
 #if BUILDFLAG(ENABLE_PRINT_CONTENT_ANALYSIS)
diff --git a/remoting/android/BUILD.gn b/remoting/android/BUILD.gn
index d19b08c..9fbffb3 100644
--- a/remoting/android/BUILD.gn
+++ b/remoting/android/BUILD.gn
@@ -183,6 +183,7 @@
     ":remoting_android_client_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/junit:junit",
diff --git a/remoting/android/client_java_tmpl.gni b/remoting/android/client_java_tmpl.gni
index bffc012..9580c5af 100644
--- a/remoting/android/client_java_tmpl.gni
+++ b/remoting/android/client_java_tmpl.gni
@@ -84,6 +84,7 @@
     deps = [
       "//base:base_java",
       "//base:jni_java",
+      "//build/android:build_java",
       "//remoting/android:remoting_android_client_java_resources",
       "//remoting/android:remoting_apk_manifest",
       "//remoting/proto/remoting/v1:directory_proto_java",
diff --git a/services/BUILD.gn b/services/BUILD.gn
index e1c133f..179e03ed 100644
--- a/services/BUILD.gn
+++ b/services/BUILD.gn
@@ -125,6 +125,7 @@
       "//base:base_java",
       "//base:base_java_test_support",
       "//base:base_junit_test_support",
+      "//build/android:build_java",
       "//mojo/public/java:base_java",
       "//mojo/public/java:bindings_java",
       "//mojo/public/java:system_java",
@@ -156,6 +157,7 @@
       "$google_play_services_package:google_play_services_vision_java",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//mojo/public/java:base_java",
       "//mojo/public/java:bindings_java",
       "//mojo/public/mojom/base:base_java",
diff --git a/services/data_decoder/public/cpp/android/BUILD.gn b/services/data_decoder/public/cpp/android/BUILD.gn
index c86f66a6..62e51d3 100644
--- a/services/data_decoder/public/cpp/android/BUILD.gn
+++ b/services/data_decoder/public/cpp/android/BUILD.gn
@@ -13,7 +13,10 @@
 
 if (current_toolchain == default_toolchain) {
   android_library("safe_json_java") {
-    deps = [ "//base:base_java" ]
+    deps = [
+      "//base:base_java",
+      "//build/android:build_java",
+    ]
     annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
     sources = [] + _jni_sources
   }
diff --git a/services/device/generic_sensor/BUILD.gn b/services/device/generic_sensor/BUILD.gn
index 53382c5..0028b06 100644
--- a/services/device/generic_sensor/BUILD.gn
+++ b/services/device/generic_sensor/BUILD.gn
@@ -172,6 +172,7 @@
     sources = device_sensors_jni_sources
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//services/device/public/mojom:generic_sensor_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
     ]
diff --git a/services/device/geolocation/BUILD.gn b/services/device/geolocation/BUILD.gn
index 85df527..ceea12d 100644
--- a/services/device/geolocation/BUILD.gn
+++ b/services/device/geolocation/BUILD.gn
@@ -168,6 +168,7 @@
       "$google_play_services_package:google_play_services_basement_java",
       "$google_play_services_package:google_play_services_location_java",
       "//base:base_java",
+      "//build/android:build_java",
       "//components/location/android:location_java",
       "//services/device/public/java:geolocation_java",
       "//third_party/android_deps:chromium_play_services_availability_java",
diff --git a/services/device/public/java/BUILD.gn b/services/device/public/java/BUILD.gn
index bb0f70b..d27fe141 100644
--- a/services/device/public/java/BUILD.gn
+++ b/services/device/public/java/BUILD.gn
@@ -6,7 +6,10 @@
 
 android_library("device_feature_list_java") {
   sources = [ "src/org/chromium/device/DeviceFeatureList.java" ]
-  deps = [ "//base:base_java" ]
+  deps = [
+    "//base:base_java",
+    "//build/android:build_java",
+  ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
 
@@ -29,6 +32,7 @@
   deps = [
     ":geolocation_java",
     "//base:base_java",
+    "//build/android:build_java",
 
     # Ideally this dependency should be removed. http://crbug.com/850357
     "//services/device/geolocation:geolocation_java",
diff --git a/services/device/time_zone_monitor/BUILD.gn b/services/device/time_zone_monitor/BUILD.gn
index 4479b61..cf8514ca 100644
--- a/services/device/time_zone_monitor/BUILD.gn
+++ b/services/device/time_zone_monitor/BUILD.gn
@@ -88,7 +88,10 @@
     # result of //services/device:java depending on it.
     visibility = [ "//services/device:*" ]
     sources = [ "android/java/src/org/chromium/device/time_zone_monitor/TimeZoneMonitor.java" ]
-    deps = [ "//base:base_java" ]
+    deps = [
+      "//base:base_java",
+      "//build/android:build_java",
+    ]
     annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
   }
 }
diff --git a/services/device/usb/BUILD.gn b/services/device/usb/BUILD.gn
index 952e013..1ca1515 100644
--- a/services/device/usb/BUILD.gn
+++ b/services/device/usb/BUILD.gn
@@ -243,6 +243,7 @@
     sources = java_sources_needing_jni
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
     ]
     annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/services/network/private_network_access_checker_unittest.cc b/services/network/private_network_access_checker_unittest.cc
index 1c23220e..5b34cdcc 100644
--- a/services/network/private_network_access_checker_unittest.cc
+++ b/services/network/private_network_access_checker_unittest.cc
@@ -406,20 +406,20 @@
 
   EXPECT_THAT(checker.ResponseAddressSpace(),
               Optional(mojom::IPAddressSpace::kPrivate));
-
-  checker.ResetForRedirect();
-
-  EXPECT_EQ(checker.ResponseAddressSpace(), absl::nullopt);
 }
 
 TEST(PrivateNetworkAccessCheckerTest, ProxiedTransportAddressSpaceIsUnknown) {
   mojom::URLLoaderFactoryParams factory_params;
 
   PrivateNetworkAccessChecker checker(ResourceRequest(), &factory_params,
-                                      mojom::kURLLoadOptionNone);
+                                      mojom::kURLLoadOptionBlockLocalRequest);
 
-  checker.Check(ProxiedTransport(LocalEndpoint()));
+  // This succeeds in spite of the load option, because the proxied transport
+  // is not considered any less public than `kPublic`.
+  EXPECT_EQ(checker.Check(ProxiedTransport(LocalEndpoint())),
+            Result::kAllowedMissingClientSecurityState);
 
+  // In fact, it is considered unknown.
   EXPECT_EQ(checker.ResponseAddressSpace(), mojom::IPAddressSpace::kUnknown);
 }
 
@@ -427,13 +427,18 @@
   mojom::URLLoaderFactoryParams factory_params;
 
   PrivateNetworkAccessChecker checker(ResourceRequest(), &factory_params,
-                                      mojom::kURLLoadOptionNone);
+                                      mojom::kURLLoadOptionBlockLocalRequest);
 
-  checker.Check(CachedTransport(PrivateEndpoint()));
+  // The cached transport is treated like a direct transport to the same
+  // endpoint, so the load option does not fail the check.
+  EXPECT_EQ(checker.Check(CachedTransport(PublicEndpoint())),
+            Result::kAllowedMissingClientSecurityState);
 
-  EXPECT_EQ(checker.ResponseAddressSpace(), mojom::IPAddressSpace::kPrivate);
+  EXPECT_EQ(checker.ResponseAddressSpace(), mojom::IPAddressSpace::kPublic);
 
-  checker.Check(CachedTransport(LocalEndpoint()));
+  // When the endpoint is local, the check fails as for a direct transport.
+  EXPECT_EQ(checker.Check(CachedTransport(LocalEndpoint())),
+            Result::kBlockedByLoadOption);
 
   EXPECT_EQ(checker.ResponseAddressSpace(), mojom::IPAddressSpace::kLocal);
 }
@@ -451,6 +456,11 @@
 
   // The target address space has been cleared.
   EXPECT_EQ(checker.TargetAddressSpace(), mojom::IPAddressSpace::kUnknown);
+
+  // This succeeds even though the IP address space does not match the target
+  // passed at construction time, thanks to `ResetForRedirect()`.
+  EXPECT_EQ(checker.Check(DirectTransport(LocalEndpoint())),
+            Result::kAllowedMissingClientSecurityState);
 }
 
 TEST(PrivateNetworkAccessCheckerTest, ResetForRedirectResponseAddressSpace) {
@@ -464,6 +474,11 @@
   checker.ResetForRedirect();
 
   EXPECT_EQ(checker.ResponseAddressSpace(), absl::nullopt);
+
+  // This succeeds even though the IP address space does not match that of the
+  // previous endpoint passed to `Check()`, thanks to `ResetForRedirect()`.
+  EXPECT_EQ(checker.Check(DirectTransport(LocalEndpoint())),
+            Result::kAllowedMissingClientSecurityState);
 }
 
 TEST(PrivateNetworkAccessCheckerTest,
diff --git a/services/tracing/BUILD.gn b/services/tracing/BUILD.gn
index 16658e60..7424427 100644
--- a/services/tracing/BUILD.gn
+++ b/services/tracing/BUILD.gn
@@ -176,7 +176,10 @@
 
   android_library("tracing_test_helper_java") {
     testonly = true
-    deps = [ "//base:base_java" ]
+    deps = [
+      "//base:base_java",
+      "//build/android:build_java",
+    ]
     sources = [ "android/test/src/org/chromium/tracing/UnwindTestHelper.java" ]
   }
 }
diff --git a/styleguide/c++/c++-features.md b/styleguide/c++/c++-features.md
index 22d4eb59..d209c53 100644
--- a/styleguide/c++/c++-features.md
+++ b/styleguide/c++/c++-features.md
@@ -692,6 +692,24 @@
 for regular arrays.
 ***
 
+### std::is_invocable <sup>[allowed]</sup>
+
+```c++
+std::is_invocable_v<Fn, 1, "Hello">
+```
+
+**Description:** Checks whether a function may be invoked with the given
+argument types.  The `_r` variant also evaluates whether the result is
+convertible to a given type.
+
+**Documentation:**
+[std::is_invocable](https://en.cppreference.com/w/cpp/types/is_invocable)
+
+**Notes:**
+*** promo
+[Discussion thread](https://groups.google.com/a/chromium.org/g/cxx/c/YhlF_sTDSc0/m/QMzf42BtAAAJ)
+***
+
 ## C++17 Banned Library Features {#library-blocklist-17}
 
 The following C++17 library features are not allowed in the Chromium codebase.
@@ -1295,24 +1313,6 @@
 None
 ***
 
-### std::is_invocable <sup>[tbd]</sup>
-
-```c++
-std::is_invocable_v<Fn, 1, "Hello">
-```
-
-**Description:** Checks whether a function may be invoked with the given
-argument types.  The `_r` variant also evaluates whether the result is
-convertible to a given type.
-
-**Documentation:**
-[std::is_invocable](https://en.cppreference.com/w/cpp/types/is_invocable)
-
-**Notes:**
-*** promo
-None
-***
-
 ### std::is_aggregate <sup>[tbd]</sup>
 
 ```c++
diff --git a/testing/android/native_test/BUILD.gn b/testing/android/native_test/BUILD.gn
index 57bfb044..e98bb164 100644
--- a/testing/android/native_test/BUILD.gn
+++ b/testing/android/native_test/BUILD.gn
@@ -46,7 +46,10 @@
 android_library("native_main_runner_java") {
   testonly = true
   sources = [ "java/src/org/chromium/native_test/MainRunner.java" ]
-  deps = [ "//base:base_java" ]
+  deps = [
+    "//base:base_java",
+    "//build/android:build_java",
+  ]
 }
 
 android_library("native_test_java") {
@@ -55,6 +58,7 @@
     ":native_main_runner_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
     "//testing/android/reporter:reporter_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/testing/android/reporter/BUILD.gn b/testing/android/reporter/BUILD.gn
index 1196b4f..4a6b32c 100644
--- a/testing/android/reporter/BUILD.gn
+++ b/testing/android/reporter/BUILD.gn
@@ -10,6 +10,7 @@
 
   deps = [
     "//base:base_java",
+    "//build/android:build_java",
     "//build/android/gtest_apk:native_test_instrumentation_test_runner_java",
     "//third_party/android_sdk:android_test_base_java",
   ]
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 24239ab..91ae91c7 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5876,21 +5876,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.5028.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5029.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.5028.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5029.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.5028.0",
-              "revision": "version:103.0.5028.0"
+              "location": "lacros_version_skew_tests_v103.0.5029.0",
+              "revision": "version:103.0.5029.0"
             }
           ],
           "dimension_sets": [
@@ -6018,21 +6018,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.5028.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5029.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.5028.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5029.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.5028.0",
-              "revision": "version:103.0.5028.0"
+              "location": "lacros_version_skew_tests_v103.0.5029.0",
+              "revision": "version:103.0.5029.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 975cc93..86f69d8 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -92031,21 +92031,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.5028.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5029.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.5028.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5029.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.5028.0",
-              "revision": "version:103.0.5028.0"
+              "location": "lacros_version_skew_tests_v103.0.5029.0",
+              "revision": "version:103.0.5029.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -92148,21 +92148,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.5028.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5029.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.5028.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5029.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.5028.0",
-              "revision": "version:103.0.5028.0"
+              "location": "lacros_version_skew_tests_v103.0.5029.0",
+              "revision": "version:103.0.5029.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -93540,20 +93540,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.5028.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5029.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.5028.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5029.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.5028.0",
-              "revision": "version:103.0.5028.0"
+              "location": "lacros_version_skew_tests_v103.0.5029.0",
+              "revision": "version:103.0.5029.0"
             }
           ],
           "dimension_sets": [
@@ -93682,20 +93682,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.5028.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5029.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.5028.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5029.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.5028.0",
-              "revision": "version:103.0.5028.0"
+              "location": "lacros_version_skew_tests_v103.0.5029.0",
+              "revision": "version:103.0.5029.0"
             }
           ],
           "dimension_sets": [
@@ -95237,20 +95237,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.5028.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5029.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.5028.0",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 103.0.5029.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.5028.0",
-              "revision": "version:103.0.5028.0"
+              "location": "lacros_version_skew_tests_v103.0.5029.0",
+              "revision": "version:103.0.5029.0"
             }
           ],
           "dimension_sets": [
@@ -95379,20 +95379,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.5028.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5029.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.5028.0",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 103.0.5029.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.5028.0",
-              "revision": "version:103.0.5028.0"
+              "location": "lacros_version_skew_tests_v103.0.5029.0",
+              "revision": "version:103.0.5029.0"
             }
           ],
           "dimension_sets": [
@@ -96136,20 +96136,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.5028.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5029.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.5028.0",
+        "name": "interactive_ui_tests Lacros version skew testing ash 103.0.5029.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.5028.0",
-              "revision": "version:103.0.5028.0"
+              "location": "lacros_version_skew_tests_v103.0.5029.0",
+              "revision": "version:103.0.5029.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.json b/testing/buildbot/chromium.json
index ee68ca47..ed0ad58 100644
--- a/testing/buildbot/chromium.json
+++ b/testing/buildbot/chromium.json
@@ -21,6 +21,15 @@
       "all"
     ]
   },
+  "lacros64-archive-rel": {
+    "additional_compile_targets": [
+      "chrome",
+      "lacros_version_metadata",
+      "linux_symbols",
+      "symupload",
+      "strip_chrome_binary"
+    ]
+  },
   "linux-archive-dbg": {
     "additional_compile_targets": [
       "all"
diff --git a/testing/buildbot/filters/pixel_tests.filter b/testing/buildbot/filters/pixel_tests.filter
index ee77a9d..3e076ab 100644
--- a/testing/buildbot/filters/pixel_tests.filter
+++ b/testing/buildbot/filters/pixel_tests.filter
@@ -36,7 +36,6 @@
 HungRendererDialogViewBrowserTest.*
 ImportLockDialogViewBrowserTest.*
 InlineLoginHelperBrowserTest.InvokeUi_*
-InteractionSequenceBrowserUtilInteractiveUiTest.CompareScreenshot_*
 InteractionSequenceBrowserUtilTest.CompareScreenshot_*
 LocalCardMigrationBrowserUiTest.*
 NewTabPageTest.*
@@ -63,6 +62,7 @@
 SessionCrashedBubbleViewTest.*
 TabGroupEditorBubbleViewDialogBrowserTest.*
 TabHoverCardBubbleViewBrowserTest.*
+TranslateBubbleVisualTest.InvokeUi_*
 UpdateRecommendedDialogTest.*
 WebAppConfirmViewBrowserTest.*
 ZoomBubbleDialogTest.*
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 852e86e..a7704caf 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.5028.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v103.0.5029.0/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 103.0.5028.0',
+    'identifier': 'Lacros version skew testing ash 103.0.5029.0',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v103.0.5028.0',
-          'revision': 'version:103.0.5028.0',
+          'location': 'lacros_version_skew_tests_v103.0.5029.0',
+          'revision': 'version:103.0.5029.0',
         },
       ],
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 2705fe5..758c79f 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -385,6 +385,16 @@
           'all',
         ],
       },
+      'lacros64-archive-rel': {
+        'additional_compile_targets': [
+          'chrome',
+          'lacros_version_metadata',
+          'linux_symbols',
+          'symupload',
+          'strip_chrome_binary',
+        ],
+        'os_type': 'chromeos',
+      },
       'linux-archive-dbg': {
         'additional_compile_targets': [
           'all',
diff --git a/testing/trigger_scripts/base_test_triggerer.py b/testing/trigger_scripts/base_test_triggerer.py
index 047f15f..994a28b 100755
--- a/testing/trigger_scripts/base_test_triggerer.py
+++ b/testing/trigger_scripts/base_test_triggerer.py
@@ -20,6 +20,7 @@
 import subprocess
 import sys
 import tempfile
+import time
 import logging
 import six
 
@@ -32,6 +33,8 @@
 SWARMING_GO = os.path.join(SRC_DIR, 'tools', 'luci-go',
                            'swarming' + EXECUTABLE_SUFFIX)
 
+_A_WEEK_IN_SECONDS = 60 * 60 * 24 * 7
+
 
 def _convert_to_go_swarming_args(args):
     go_args = []
@@ -182,6 +185,11 @@
         for tag in sorted(tags):
             args.extend(['-tag', tag])
 
+        # If a query uses a general dimension value, e.g., os:Mac, it will take
+        # forever. We now limited the time range to be within a week.
+        start_epoch_time = int(time.time()) - _A_WEEK_IN_SECONDS
+        args.extend(['-start', str(start_epoch_time)])
+
         if limit is not None:
             args.extend(['-limit', str(limit)])
 
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 428a1fc..8be37bb 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1868,6 +1868,21 @@
             ]
         }
     ],
+    "CaptureModeSelfieCamera": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "EnableCaptureModeSelfieCamera",
+                    "enable_features": [
+                        "CaptureModeSelfieCamera"
+                    ]
+                }
+            ]
+        }
+    ],
     "CctClientDataHeader": [
         {
             "platforms": [
@@ -7707,6 +7722,29 @@
             ]
         }
     ],
+    "UserAgentOverrideExperiment": [
+        {
+            "platforms": [
+                "android",
+                "android_weblayer",
+                "android_webview",
+                "chromeos",
+                "chromeos_lacros",
+                "ios",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "UserAgentOverrideExperiment"
+                    ]
+                }
+            ]
+        }
+    ],
     "UserCloudSigninRestrictionPolicyFetcher": [
         {
             "platforms": [
diff --git a/third_party/android_deps/local_modifications/preconditions/javatests/BUILD.gn b/third_party/android_deps/local_modifications/preconditions/javatests/BUILD.gn
index 6d0964b..ff763309 100644
--- a/third_party/android_deps/local_modifications/preconditions/javatests/BUILD.gn
+++ b/third_party/android_deps/local_modifications/preconditions/javatests/BUILD.gn
@@ -12,6 +12,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//third_party/android_deps:guava_android_java",
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/junit",
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index 65f5f790..2e9fedd9 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -303,6 +303,7 @@
   if (is_android) {
     deps += [
       "//base:base_java",
+      "//build/android:build_java",
       "//media/base/android:media_java",
     ]
   }
diff --git a/third_party/blink/renderer/controller/BUILD.gn b/third_party/blink/renderer/controller/BUILD.gn
index 5be56fd..07f5a8bd 100644
--- a/third_party/blink/renderer/controller/BUILD.gn
+++ b/third_party/blink/renderer/controller/BUILD.gn
@@ -138,6 +138,7 @@
   if (is_android) {
     deps += [
       "//base:base_java",
+      "//build/android:build_java",
       "//content/public/android:content_java",
       "//content/shell/android:content_shell_assets",
       "//net/android:net_java",
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
index 6588d78..2f5c97f 100644
--- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -840,12 +840,7 @@
       style.OverflowY() != EOverflow::kVisible)
     AdjustOverflow(style, element);
 
-  // TODO(rego): When HighlightInheritance (https://crbug.com/1024156) is
-  // enabled, we're going to inherit the text decorations from the parent
-  // elements, that would cause that we paint the decorations more than once in
-  // the highlight pseudos. This doesn't seem right and there's a spec issue
-  // (https://github.com/w3c/csswg-drafts/issues/6829) about not propagating
-  // text decorations on highlights pseudos.
+  // Highlight pseudos propagate decorations with inheritance only.
   if (StopPropagateTextDecorations(style, element) || state.IsForHighlight())
     style.ClearAppliedTextDecorations();
   else
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
index 95f4bd1a..a72af66 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -233,8 +233,6 @@
   if (resolver.AuthorFlags() & CSSProperty::kBorderRadius)
     state_.Style()->SetHasAuthorBorderRadius();
 
-  // TODO(crbug.com/1024156): spec issue: user origin?
-  // TODO(crbug.com/1024156): https://github.com/w3c/csswg-drafts/issues/6386
   if ((state_.Style()->InsideLink() != EInsideLink::kInsideVisitedLink &&
        (resolver.AuthorFlags() & CSSProperty::kHighlightColors)) ||
       (state_.Style()->InsideLink() == EInsideLink::kInsideVisitedLink &&
diff --git a/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc b/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc
index 53a2987..081ea7d 100644
--- a/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc
+++ b/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc
@@ -60,8 +60,8 @@
   bool is_feature_enabled =
       base::FeatureList::IsEnabled(features::kNavigationPredictor);
   const KURL& url = document.BaseURL();
-  return is_feature_enabled && document.IsInMainFrame() && url.IsValid() &&
-         url.ProtocolIs("https");
+  return is_feature_enabled && document.IsInOutermostMainFrame() &&
+         url.IsValid() && url.ProtocolIs("https");
 }
 
 void AnchorElementMetricsSender::MaybeReportClickedMetricsOnClick(
@@ -118,7 +118,7 @@
 AnchorElementMetricsSender::AnchorElementMetricsSender(Document& document)
     : Supplement<Document>(document),
       metrics_host_(document.GetExecutionContext()) {
-  DCHECK(document.IsInMainFrame());
+  DCHECK(document.IsInOutermostMainFrame());
 
   document.View()->RegisterForLifecycleNotifications(this);
   intersection_observer_ = IntersectionObserver::Create(
diff --git a/third_party/blink/renderer/core/html/html_script_element.cc b/third_party/blink/renderer/core/html/html_script_element.cc
index 227b7972..8706b22 100644
--- a/third_party/blink/renderer/core/html/html_script_element.cc
+++ b/third_party/blink/renderer/core/html/html_script_element.cc
@@ -84,11 +84,6 @@
   children_changed_by_api_ |= !change.ByParser();
 }
 
-void HTMLScriptElement::DidMoveToNewDocument(Document& old_document) {
-  ScriptRunner::MovePendingScript(old_document, GetDocument(), loader_.Get());
-  HTMLElement::DidMoveToNewDocument(old_document);
-}
-
 void HTMLScriptElement::ParseAttribute(
     const AttributeModificationParams& params) {
   if (params.name == html_names::kSrcAttr) {
diff --git a/third_party/blink/renderer/core/html/html_script_element.h b/third_party/blink/renderer/core/html/html_script_element.h
index 6a5b774..1203c8b 100644
--- a/third_party/blink/renderer/core/html/html_script_element.h
+++ b/third_party/blink/renderer/core/html/html_script_element.h
@@ -86,7 +86,6 @@
 
   void DidNotifySubtreeInsertionsToDocument() override;
   void ChildrenChanged(const ChildrenChange&) override;
-  void DidMoveToNewDocument(Document& old_document) override;
 
   bool IsURLAttribute(const Attribute&) const override;
   bool HasLegalLinkAttribute(const QualifiedName&) const override;
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc
index b59da01..a1bddc5 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -4701,10 +4701,12 @@
 void HTMLMediaElement::SetError(MediaError* error) {
   error_ = error;
 
-  if (!error || !media_source_attachment_)
-    return;
-
-  media_source_attachment_->OnElementError();
+  if (error) {
+    DLOG(ERROR) << __func__ << ": {code=" << error->code()
+                << ", message=" << error->message() << "}";
+    if (media_source_attachment_)
+      media_source_attachment_->OnElementError();
+  }
 }
 
 void HTMLMediaElement::ReportCurrentTimeToMediaSource() {
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
index 4731f89..088053a 100644
--- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
@@ -162,29 +162,6 @@
   return AxisEdge::kStart;
 }
 
-// We are interested in cases where the flex item *may* expand due to
-// fragmentation (lines pushed down by a fragmentation line, etc).
-bool MinBlockSizeShouldEncompassIntrinsicSize(const NGFlexItem& item) {
-  // If this item has (any) descendant that is percentage based, we can end
-  // up in a situation where we'll constantly try and expand the row. E.g.
-  // <div style="display: flex;">
-  //   <div style="min-height: 100px;">
-  //     <div style="height: 200%;"></div>
-  //   </div>
-  // </div>
-  if (item.has_descendant_that_depends_on_percentage_block_size)
-    return false;
-
-  if (item.ng_input_node.IsMonolithic())
-    return false;
-
-  // TODO(almaher): Figure out which cases this should be true. (Should this
-  // only be true when min-block-size is auto in the case of |is_column_|?)
-  // Also, should this be the same in the case of a row flex container?
-  const auto& item_style = item.ng_input_node.Style();
-  return item_style.LogicalHeight().IsAutoOrContentOrIntrinsic();
-}
-
 }  // namespace
 
 void NGFlexLayoutAlgorithm::HandleOutOfFlowPositionedItems(
@@ -2405,6 +2382,57 @@
   return algorithm_with_row_cross_sizes.Layout();
 }
 
+// We are interested in cases where the flex item *may* expand due to
+// fragmentation (lines pushed down by a fragmentation line, etc).
+bool NGFlexLayoutAlgorithm::MinBlockSizeShouldEncompassIntrinsicSize(
+    const NGFlexItem& item) const {
+  // If this item has (any) descendant that is percentage based, we can end
+  // up in a situation where we'll constantly try and expand the row. E.g.
+  // <div style="display: flex;">
+  //   <div style="min-height: 100px;">
+  //     <div style="height: 200%;"></div>
+  //   </div>
+  // </div>
+  if (item.has_descendant_that_depends_on_percentage_block_size)
+    return false;
+
+  if (item.ng_input_node.IsMonolithic())
+    return false;
+
+  const auto& item_style = item.ng_input_node.Style();
+
+  // NOTE: We currently assume that writing-mode roots are monolithic, but
+  // this may change in the future.
+  DCHECK_EQ(ConstraintSpace().GetWritingDirection().GetWritingMode(),
+            item_style.GetWritingMode());
+
+  if (is_column_) {
+    bool can_shrink = item_style.ResolvedFlexShrink(Style()) != 0.f &&
+                      !Style().LogicalHeight().IsAutoOrContentOrIntrinsic();
+
+    // Only allow growth if the item can't shrink and the flex-basis is
+    // content-based.
+    if (!IsUsedFlexBasisDefinite(item.ng_input_node) && !can_shrink)
+      return true;
+
+    // Only allow growth if the item's block-size is auto and either the item
+    // can't shrink or its min-height is auto.
+    if (item_style.LogicalHeight().IsAutoOrContentOrIntrinsic() &&
+        (!can_shrink || algorithm_.ShouldApplyMinSizeAutoForChild(
+                            *item.ng_input_node.GetLayoutBox())))
+      return true;
+  } else {
+    // Don't grow if the item's block-size should be the same as its container.
+    if (WillChildCrossSizeBeContainerCrossSize(item.ng_input_node))
+      return false;
+
+    // Only allow growth if the item's cross size is auto.
+    if (DoesItemCrossSizeComputeToAuto(item.ng_input_node))
+      return true;
+  }
+  return false;
+}
+
 #if DCHECK_IS_ON()
 void NGFlexLayoutAlgorithm::CheckFlexLines(
     HeapVector<NGFlexLine>& flex_line_outputs) const {
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
index 5278b1f..abc4629 100644
--- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
@@ -17,6 +17,7 @@
 class NGBlockBreakToken;
 class NGBoxFragment;
 struct DevtoolsFlexInfo;
+struct NGFlexItem;
 
 class CORE_EXPORT NGFlexLayoutAlgorithm
     : public NGLayoutAlgorithm<NGBlockNode,
@@ -174,6 +175,10 @@
   // cross-size adjustments.
   const NGLayoutResult* RelayoutWithNewRowSizes();
 
+  // Used to determine when to allow an item to expand as a result of
+  // fragmentation.
+  bool MinBlockSizeShouldEncompassIntrinsicSize(const NGFlexItem& item) const;
+
 #if DCHECK_IS_ON()
   void CheckFlexLines(HeapVector<NGFlexLine>& flex_line_outputs) const;
 #endif
diff --git a/third_party/blink/renderer/core/messaging/message_port.cc b/third_party/blink/renderer/core/messaging/message_port.cc
index a284d18..b72ede668 100644
--- a/third_party/blink/renderer/core/messaging/message_port.cc
+++ b/third_party/blink/renderer/core/messaging/message_port.cc
@@ -56,7 +56,11 @@
 namespace blink {
 
 MessagePort::MessagePort(ExecutionContext& execution_context)
-    : ExecutionContextLifecycleObserver(&execution_context),
+    : ExecutionContextLifecycleObserver(execution_context.IsContextDestroyed()
+                                            ? nullptr
+                                            : &execution_context),
+      // Ports in a destroyed context start out in a closed state.
+      closed_(execution_context.IsContextDestroyed()),
       task_runner_(execution_context.GetTaskRunner(TaskType::kPostedMessage)) {}
 
 MessagePort::~MessagePort() {
@@ -168,10 +172,21 @@
   DCHECK(port.IsValid());
   DCHECK(!connector_);
 
+  // If the context was already destroyed, there is no reason to actually
+  // entangle the port and create a Connector. No messages will ever be able to
+  // be sent or received anyway, as StartReceiving will never be called.
+  if (!GetExecutionContext())
+    return;
+
   port_ = std::move(port);
   connector_ = std::make_unique<mojo::Connector>(
       port_.TakeHandleToEntangle(GetExecutionContext()),
       mojo::Connector::SINGLE_THREADED_SEND);
+  // The raw `this` is safe despite `this` being a garbage collected object
+  // because we make sure that:
+  // 1. This object will not be garbage collected while it is connected and
+  //    the execution context is not destroyed, and
+  // 2. when the execution context is destroyed, the connector_ is reset.
   connector_->set_incoming_receiver(this);
   connector_->set_connection_error_handler(
       WTF::Bind(&MessagePort::close, WrapWeakPersistent(this)));
diff --git a/third_party/blink/renderer/core/messaging/message_port.h b/third_party/blink/renderer/core/messaging/message_port.h
index c5e0fef..30d13d1 100644
--- a/third_party/blink/renderer/core/messaging/message_port.h
+++ b/third_party/blink/renderer/core/messaging/message_port.h
@@ -141,7 +141,7 @@
   std::unique_ptr<mojo::Connector> connector_;
 
   bool started_ = false;
-  bool closed_ = false;
+  bool closed_;
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
diff --git a/third_party/blink/renderer/core/paint/highlight_painting_utils.cc b/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
index a352e105..f9d7601 100644
--- a/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
+++ b/third_party/blink/renderer/core/paint/highlight_painting_utils.cc
@@ -182,12 +182,6 @@
 // highlight color properties default to initial, rather than the UA default.
 // https://drafts.csswg.org/css-pseudo-4/#highlight-cascade
 bool UseUaHighlightColors(PseudoId pseudo, const ComputedStyle& pseudo_style) {
-  // TODO(crbug.com/1024156): spec issue: should we limit this to ::selection?
-  // TODO(crbug.com/1024156): https://github.com/w3c/csswg-drafts/issues/6386
-  // NOTE: to limit this to ::selection without breaking our default highlight
-  // colors for ::target-text, we would need to split HasAuthorHighlightColors
-  // into bits for foreground and background, or impl ::target-text defaults
-  // as a UA stylesheet rule of MarkText on Mark (as recommended by the spec).
   return !pseudo_style.HasAuthorHighlightColors();
 }
 
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index 417055a..af19571 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -724,8 +724,6 @@
   } else if (LayoutBox* box = GetLayoutBox()) {
     size_ = box->Size();
   }
-  if (old_size != size_)
-    MarkAncestorChainForFlagsUpdate();
 
   return old_size != size_;
 }
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc
index 0a9ddf9..b33b1e2 100644
--- a/third_party/blink/renderer/core/script/script_loader.cc
+++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -122,12 +122,11 @@
 void ScriptLoader::Trace(Visitor* visitor) const {
   visitor->Trace(element_);
   visitor->Trace(parser_document_);
-  visitor->Trace(pending_script_);
   visitor->Trace(prepared_pending_script_);
   visitor->Trace(resource_keep_alive_);
   visitor->Trace(script_web_bundle_);
   visitor->Trace(speculation_rule_set_);
-  PendingScriptClient::Trace(visitor);
+  ResourceFinishObserver::Trace(visitor);
 }
 
 void ScriptLoader::DidNotifySubtreeInsertionsToDocument() {
@@ -172,13 +171,6 @@
   }
 }
 
-void ScriptLoader::DetachPendingScript() {
-  if (!pending_script_)
-    return;
-  pending_script_->Dispose();
-  pending_script_ = nullptr;
-}
-
 namespace {
 
 // <specdef href="https://html.spec.whatwg.org/C/#prepare-a-script">
@@ -990,15 +982,13 @@
     // that will execute in order as soon as possible associated with the node
     // document of the script element at the time the prepare a script algorithm
     // started. ...</spec>
-    pending_script_ = TakePendingScript(ScriptSchedulingType::kInOrder);
+    //
     // TODO(hiroshige): Here the context document is used as "node document"
     // while Step 14 uses |elementDocument| as "node document". Fix this.
     context_window->document()->GetScriptRunner()->QueueScriptForExecution(
-        pending_script_);
-    // Note that watchForLoad can immediately call pendingScriptFinished.
-    pending_script_->WatchForLoad(this);
+        TakePendingScript(ScriptSchedulingType::kInOrder));
     // The part "When the script is ready..." is implemented in
-    // ScriptRunner::notifyScriptReady().
+    // ScriptRunner::PendingScriptFinished().
     // TODO(hiroshige): Annotate it.
 
     return true;
@@ -1016,15 +1006,13 @@
     // element at the time the prepare a script algorithm started. When the
     // script is ready, execute the script block and then remove the element
     // from the set of scripts that will execute as soon as possible.</spec>
-    pending_script_ = TakePendingScript(ScriptSchedulingType::kAsync);
+    //
     // TODO(hiroshige): Here the context document is used as "node document"
     // while Step 14 uses |elementDocument| as "node document". Fix this.
     context_window->document()->GetScriptRunner()->QueueScriptForExecution(
-        pending_script_);
-    // Note that watchForLoad can immediately call pendingScriptFinished.
-    pending_script_->WatchForLoad(this);
+        TakePendingScript(ScriptSchedulingType::kAsync));
     // The part "When the script is ready..." is implemented in
-    // ScriptRunner::notifyScriptReady().
+    // ScriptRunner::PendingScriptFinished().
     // TODO(hiroshige): Annotate it.
 
     return true;
@@ -1093,6 +1081,10 @@
       url, document, options, cross_origin, encoding, element_, defer);
   prepared_pending_script_ = pending_script;
   resource_keep_alive_ = pending_script->GetResource();
+  if (resource_keep_alive_) {
+    resource_keep_alive_->AddFinishObserver(
+        this, document.GetTaskRunner(TaskType::kNetworking).get());
+  }
 }
 
 // <specdef href="https://html.spec.whatwg.org/C/#prepare-a-script">
@@ -1126,13 +1118,7 @@
   return pending_script;
 }
 
-void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) {
-  DCHECK(!will_be_parser_executed_);
-  DCHECK_EQ(pending_script_, pending_script);
-  DCHECK(pending_script->IsControlledByScriptRunner());
-  DCHECK(pending_script_->GetSchedulingType() == ScriptSchedulingType::kAsync ||
-         pending_script_->GetSchedulingType() ==
-             ScriptSchedulingType::kInOrder);
+void ScriptLoader::NotifyFinished() {
   // Historically we clear |resource_keep_alive_| when the scheduling type is
   // kAsync or kInOrder (crbug.com/778799). But if the script resource was
   // served via signed exchange, the script may not be in the HTTPCache, and
@@ -1145,18 +1131,6 @@
           blink::features::kKeepScriptResourceAlive)) {
     resource_keep_alive_ = nullptr;
   }
-
-  if (!element_->GetExecutionContext()) {
-    DetachPendingScript();
-    return;
-  }
-
-  LocalDOMWindow* context_window =
-      To<LocalDOMWindow>(element_->GetExecutionContext());
-  context_window->document()->GetScriptRunner()->NotifyScriptReady(
-      pending_script);
-  pending_script_->StopWatchingForLoad();
-  pending_script_ = nullptr;
 }
 
 bool ScriptLoader::IgnoresLoadRequest() const {
@@ -1192,12 +1166,6 @@
          EqualIgnoringASCIICase(event_attribute, "onload()");
 }
 
-PendingScript*
-ScriptLoader::GetPendingScriptIfControlledByScriptRunnerForCrossDocMove() {
-  DCHECK(!pending_script_ || pending_script_->IsControlledByScriptRunner());
-  return pending_script_;
-}
-
 String ScriptLoader::GetScriptText() const {
   // Step 3 of
   // https://w3c.github.io/webappsec-trusted-types/dist/spec/#abstract-opdef-prepare-the-script-url-and-text
diff --git a/third_party/blink/renderer/core/script/script_loader.h b/third_party/blink/renderer/core/script/script_loader.h
index bd25737..368d588 100644
--- a/third_party/blink/renderer/core/script/script_loader.h
+++ b/third_party/blink/renderer/core/script/script_loader.h
@@ -22,17 +22,12 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_LOADER_H_
 
 #include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h"
-#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_source_location_type.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/html/cross_origin_attribute.h"
 #include "third_party/blink/renderer/core/script/pending_script.h"
-#include "third_party/blink/renderer/core/script/script.h"
-#include "third_party/blink/renderer/core/script/script_runner.h"
 #include "third_party/blink/renderer/core/script/script_scheduling_type.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
-#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_finish_observer.h"
 #include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
 #include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
 #include "third_party/blink/renderer/platform/wtf/text/text_position.h"
@@ -49,14 +44,14 @@
 class SpeculationRuleSet;
 class Modulator;
 
-class CORE_EXPORT ScriptLoader final : public GarbageCollected<ScriptLoader>,
-                                       public PendingScriptClient,
+class CORE_EXPORT ScriptLoader final : public ResourceFinishObserver,
                                        public NameClient {
  public:
   ScriptLoader(ScriptElementBase*, const CreateElementFlags);
   ~ScriptLoader() override;
   void Trace(Visitor*) const override;
   const char* NameInHeapSnapshot() const override { return "ScriptLoader"; }
+  String DebugName() const override { return "ScriptLoader"; }
 
   enum LegacyTypeSupport {
     kDisallowLegacyTypeInTypeAttribute,
@@ -114,11 +109,6 @@
 
   void SetFetchDocWrittenScriptDeferIdle();
 
-  // Return non-null if controlled by ScriptRunner, or null otherwise.
-  // Only for ScriptRunner::MovePendingScript() and should be removed once
-  // crbug.com/721914 is fixed.
-  PendingScript* GetPendingScriptIfControlledByScriptRunnerForCrossDocMove();
-
  private:
   bool IgnoresLoadRequest() const;
   bool IsScriptForEventSupported() const;
@@ -139,11 +129,10 @@
                              Modulator*,
                              const ScriptFetchOptions&);
 
-  // Clears the connection to the PendingScript.
-  void DetachPendingScript();
-
-  // PendingScriptClient
-  void PendingScriptFinished(PendingScript*) override;
+  // ResourceFinishObserver. This should be used only for managing
+  // `resource_keep_alive_` lifetime and shouldn't be used for script
+  // evaluation.
+  void NotifyFinished() override;
 
   // Get the effective script text (after Trusted Types checking).
   String GetScriptText() const;
@@ -206,13 +195,6 @@
   // to the PendingScript instead and |prepared_pending_script_| is cleared.
   Member<PendingScript> prepared_pending_script_;
 
-  // If the script is controlled by ScriptRunner, then
-  // ScriptLoader::pending_script_ holds a reference to the PendingScript and
-  // ScriptLoader is its client.
-  // Otherwise, HTMLParserScriptRunner or XMLParserScriptRunner holds the
-  // reference and |pending_script_| here is null.
-  Member<PendingScript> pending_script_;
-
   // This is used only to keep the ScriptResource of a classic script alive
   // and thus to keep it on MemoryCache, even after script execution, as long
   // as ScriptLoader is alive. crbug.com/778799
diff --git a/third_party/blink/renderer/core/script/script_runner.cc b/third_party/blink/renderer/core/script/script_runner.cc
index 67cebbc0..922cfff 100644
--- a/third_party/blink/renderer/core/script/script_runner.cc
+++ b/third_party/blink/renderer/core/script/script_runner.cc
@@ -67,9 +67,14 @@
       NOTREACHED();
       break;
   }
+
+  // Note that WatchForLoad() can immediately call PendingScriptFinished().
+  pending_script->WatchForLoad(this);
 }
 
-void ScriptRunner::NotifyScriptReady(PendingScript* pending_script) {
+void ScriptRunner::PendingScriptFinished(PendingScript* pending_script) {
+  pending_script->StopWatchingForLoad();
+
   switch (pending_script->GetSchedulingType()) {
     case ScriptSchedulingType::kAsync:
       CHECK(pending_async_scripts_.Contains(pending_script));
@@ -98,58 +103,6 @@
   }
 }
 
-bool ScriptRunner::RemovePendingInOrderScript(PendingScript* pending_script) {
-  auto it = std::find(pending_in_order_scripts_.begin(),
-                      pending_in_order_scripts_.end(), pending_script);
-  if (it == pending_in_order_scripts_.end())
-    return false;
-  pending_in_order_scripts_.erase(it);
-  return true;
-}
-
-void ScriptRunner::MovePendingScript(Document& old_document,
-                                     Document& new_document,
-                                     ScriptLoader* script_loader) {
-  Document* new_context_document =
-      new_document.GetExecutionContext()
-          ? To<LocalDOMWindow>(new_document.GetExecutionContext())->document()
-          : &new_document;
-  Document* old_context_document =
-      old_document.GetExecutionContext()
-          ? To<LocalDOMWindow>(old_document.GetExecutionContext())->document()
-          : &old_document;
-  if (old_context_document == new_context_document)
-    return;
-
-  PendingScript* pending_script =
-      script_loader
-          ->GetPendingScriptIfControlledByScriptRunnerForCrossDocMove();
-  if (!pending_script) {
-    // The ScriptLoader is not controlled by ScriptRunner. This can happen
-    // because MovePendingScript() is called for all <script> elements
-    // moved between Documents, not only for those controlled by ScriptRunner.
-    return;
-  }
-
-  old_context_document->GetScriptRunner()->MovePendingScript(
-      new_context_document->GetScriptRunner(), pending_script);
-}
-
-void ScriptRunner::MovePendingScript(ScriptRunner* new_runner,
-                                     PendingScript* pending_script) {
-  auto it = pending_async_scripts_.find(pending_script);
-  if (it != pending_async_scripts_.end()) {
-    new_runner->QueueScriptForExecution(pending_script);
-    pending_async_scripts_.erase(it);
-    document_->DecrementLoadEventDelayCount();
-    return;
-  }
-  if (RemovePendingInOrderScript(pending_script)) {
-    new_runner->QueueScriptForExecution(pending_script);
-    document_->DecrementLoadEventDelayCount();
-  }
-}
-
 void ScriptRunner::ExecutePendingScript(PendingScript* pending_script) {
   TRACE_EVENT("blink", "ScriptRunner::ExecutePendingScript");
 
@@ -165,6 +118,7 @@
   visitor->Trace(document_);
   visitor->Trace(pending_in_order_scripts_);
   visitor->Trace(pending_async_scripts_);
+  PendingScriptClient::Trace(visitor);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/script/script_runner.h b/third_party/blink/renderer/core/script/script_runner.h
index b937e872..d532292 100644
--- a/third_party/blink/renderer/core/script/script_runner.h
+++ b/third_party/blink/renderer/core/script/script_runner.h
@@ -28,7 +28,7 @@
 
 #include "base/task/single_thread_task_runner.h"
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
+#include "third_party/blink/renderer/core/script/pending_script.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_deque.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
@@ -38,12 +38,10 @@
 namespace blink {
 
 class Document;
-class PendingScript;
-class ScriptLoader;
 
-class CORE_EXPORT ScriptRunner final
-    : public GarbageCollected<ScriptRunner>,
-      public NameClient {
+class CORE_EXPORT ScriptRunner final : public GarbageCollected<ScriptRunner>,
+                                       public PendingScriptClient,
+                                       public NameClient {
  public:
   explicit ScriptRunner(Document*);
   ~ScriptRunner() override = default;
@@ -51,21 +49,18 @@
   ScriptRunner& operator=(const ScriptRunner&) = delete;
 
   void QueueScriptForExecution(PendingScript*);
-  void NotifyScriptReady(PendingScript*);
-
-  static void MovePendingScript(Document&, Document&, ScriptLoader*);
 
   void SetTaskRunnerForTesting(base::SingleThreadTaskRunner* task_runner) {
     task_runner_ = task_runner;
   }
 
-  void Trace(Visitor*) const;
+  void Trace(Visitor*) const override;
   const char* NameInHeapSnapshot() const override { return "ScriptRunner"; }
 
- private:
-  void MovePendingScript(ScriptRunner*, PendingScript*);
-  bool RemovePendingInOrderScript(PendingScript*);
+  // PendingScriptClient
+  void PendingScriptFinished(PendingScript*) override;
 
+ private:
   // Execute the given pending script.
   void ExecutePendingScript(PendingScript*);
 
diff --git a/third_party/blink/renderer/core/script/script_runner_test.cc b/third_party/blink/renderer/core/script/script_runner_test.cc
index f25714ea..21479dd7 100644
--- a/third_party/blink/renderer/core/script/script_runner_test.cc
+++ b/third_party/blink/renderer/core/script/script_runner_test.cc
@@ -100,7 +100,7 @@
  protected:
   void NotifyScriptReady(MockPendingScript* pending_script) {
     pending_script->SetIsReady(true);
-    script_runner_->NotifyScriptReady(pending_script);
+    script_runner_->PendingScriptFinished(pending_script);
   }
 
   void QueueScriptForExecution(MockPendingScript* pending_script) {
diff --git a/third_party/blink/renderer/core/svg/svg_script_element.cc b/third_party/blink/renderer/core/svg/svg_script_element.cc
index 0f04b3b..c1538c9 100644
--- a/third_party/blink/renderer/core/svg/svg_script_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_script_element.cc
@@ -83,11 +83,6 @@
   loader_->ChildrenChanged();
 }
 
-void SVGScriptElement::DidMoveToNewDocument(Document& old_document) {
-  ScriptRunner::MovePendingScript(old_document, GetDocument(), loader_.Get());
-  SVGElement::DidMoveToNewDocument(old_document);
-}
-
 bool SVGScriptElement::IsURLAttribute(const Attribute& attribute) const {
   return attribute.GetName() == AtomicString(SourceAttributeValue());
 }
diff --git a/third_party/blink/renderer/core/svg/svg_script_element.h b/third_party/blink/renderer/core/svg/svg_script_element.h
index 7b968a14..584d5dd7 100644
--- a/third_party/blink/renderer/core/svg/svg_script_element.h
+++ b/third_party/blink/renderer/core/svg/svg_script_element.h
@@ -62,7 +62,6 @@
   InsertionNotificationRequest InsertedInto(ContainerNode&) override;
   void DidNotifySubtreeInsertionsToDocument() override;
   void ChildrenChanged(const ChildrenChange&) override;
-  void DidMoveToNewDocument(Document& old_document) override;
 
   void SvgAttributeChanged(const SvgAttributeChangedParams&) override;
   bool IsURLAttribute(const Attribute&) const override;
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 5fa0e683..c18f80c 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -5032,89 +5032,130 @@
 }
 
 void WebGLRenderingContextBase::TexImageSkImage(TexImageParams params,
-                                                const SkImage* image,
+                                                sk_sp<SkImage> image,
                                                 bool image_has_flip_y) {
   const char* func_name = GetTexImageFunctionName(params.function_id);
 
-  // Read `sk_image` into `pixmap`. Use `pixmap_data` as backing storage if
-  // `pixmap` cannot directly reference `sk_image`'s data.
-  SkPixmap pixmap;
-  Vector<uint8_t> pixmap_data;
-  const SkImageInfo sk_image_info = image->imageInfo();
-  if (!image->peekPixels(&pixmap) ||
-      pixmap.rowBytes() != sk_image_info.minRowBytes()) {
-    pixmap_data.resize(
-        base::checked_cast<wtf_size_t>(sk_image_info.computeMinByteSize()));
-    pixmap = SkPixmap(sk_image_info, pixmap_data.data(),
-                      sk_image_info.minRowBytes());
-    if (!image->readPixels(pixmap, 0, 0)) {
-      SynthesizeGLError(GL_OUT_OF_MEMORY, func_name, "bad image data");
-    }
-  }
-  TexImageSkPixmap(params, &pixmap, image_has_flip_y);
-}
-
-void WebGLRenderingContextBase::TexImageSkPixmap(TexImageParams params,
-                                                 const SkPixmap* pixmap,
-                                                 bool pixmap_has_flip_y) {
-  if (!params.width)
-    params.width = pixmap->width();
-  if (!params.height)
-    params.height = pixmap->height();
-  if (!params.depth)
-    params.depth = 1;
-
-  const char* func_name = GetTexImageFunctionName(params.function_id);
   bool selecting_sub_rectangle = false;
-  if (!ValidateTexImageSubRectangle(params, pixmap, &selecting_sub_rectangle)) {
+  if (!ValidateTexImageSubRectangle(params, image.get(),
+                                    &selecting_sub_rectangle)) {
     return;
   }
 
-  // Let `gl_data` be the data that is passed to the GL upload function.
-  const void* gl_data = pixmap->addr();
+  // Ensure that `image` have a color space, because SkImageInfo::readPixels and
+  // SkPixmap::readPixels will fail if the source has no color space but the
+  // destination does.
+  if (!image->colorSpace())
+    image = image->reinterpretColorSpace(SkColorSpace::MakeSRGB());
+
+  // The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented,
+  // use GL_FLOAT instead.
+  if (params.type == GL_UNSIGNED_INT_10F_11F_11F_REV)
+    params.type = GL_FLOAT;
 
   // We will need to flip vertically if the unpack state for flip Y does not
   // match the source state for flip Y.
-  const bool do_flip_y = pixmap_has_flip_y != params.unpack_flip_y;
+  const bool do_flip_y = image_has_flip_y != params.unpack_flip_y;
+
+  // Let `converted_info` be `image`'s info, with adjustments for sub-rect
+  // selection, alpha type, color type, and color space. Let `converted_x` and
+  // `converted_y` be the origin in `image` at which the data is to be read.
+  // We will convert `image` to this format (using SkImage::readPixels), if
+  // it is not already in this format.
+  SkImageInfo converted_info = image->imageInfo();
+  int converted_x = 0;
+  int converted_y = 0;
+  {
+    // Set the size and offset parameters for the readPixels call, so we only
+    // convert the portion of `image` that is needed. Do not try this if we are
+    // uploading a 3D volume (just convert the full image in that case).
+    if (params.width.has_value() && params.height.has_value() &&
+        params.depth.value_or(1) == 1) {
+      converted_info = converted_info.makeWH(*params.width, *params.height);
+      converted_x = params.unpack_skip_pixels;
+      converted_y = params.unpack_skip_rows;
+      if (do_flip_y) {
+        converted_y = image->height() - converted_info.height() - converted_y;
+      }
+      params.unpack_skip_pixels = 0;
+      params.unpack_skip_rows = 0;
+      selecting_sub_rectangle = false;
+    }
+
+    // Set the alpha type to perform premultiplication or unmultiplication
+    // during readPixels, if needed. If the input is opaque, do not change it
+    // (readPixels fails if the source is opaque and the destination is not).
+    if (converted_info.alphaType() != kOpaque_SkAlphaType) {
+      converted_info = converted_info.makeAlphaType(
+          params.unpack_premultiply_alpha ? kPremul_SkAlphaType
+                                          : kUnpremul_SkAlphaType);
+    }
+
+    // Set the color type to perform pixel format conversion during readPixels,
+    // if possible.
+    converted_info = converted_info.makeColorType(
+        WebGLImageConversion::DataFormatToSkColorType(
+            WebGLImageConversion::GetDataFormat(params.format, params.type),
+            converted_info.colorType()));
+
+    // Set the color space to perform color space conversion to the unpack color
+    // space during readPixels, if needed.
+    converted_info = converted_info.makeColorSpace(
+        PredefinedColorSpaceToSkColorSpace(unpack_color_space_));
+  }
+
+  // Try to access `image`'s pixels directly. If they already match
+  // `converted_info` and `converted_x` and `converted_y` are zero, then use
+  // them directly. Otherwise, convert them using SkImage::readPixels.
+  SkBitmap converted_bitmap;
+  SkPixmap pixmap;
+  if (!image->peekPixels(&pixmap) || pixmap.info() != converted_info ||
+      pixmap.rowBytes() != converted_info.minRowBytes() || converted_x != 0 ||
+      converted_y != 0) {
+    converted_bitmap.allocPixels(converted_info);
+    pixmap = converted_bitmap.pixmap();
+    if (!image->readPixels(pixmap, converted_x, converted_y)) {
+      SynthesizeGLError(GL_OUT_OF_MEMORY, func_name, "bad image data");
+      return;
+    }
+  }
+
+  // Let `gl_data` be the data that is passed to the GL upload function.
+  const void* gl_data = pixmap.addr();
 
   // We will premultiply or unpremultiply only if there is a mismatch between
   // the source and the requested premultiplication format.
   WebGLImageConversion::AlphaOp alpha_op =
       WebGLImageConversion::kAlphaDoNothing;
   if (params.unpack_premultiply_alpha &&
-      pixmap->alphaType() == kUnpremul_SkAlphaType) {
+      pixmap.alphaType() == kUnpremul_SkAlphaType) {
     alpha_op = WebGLImageConversion::kAlphaDoPremultiply;
   }
   if (!params.unpack_premultiply_alpha &&
-      pixmap->alphaType() == kPremul_SkAlphaType) {
+      pixmap.alphaType() == kPremul_SkAlphaType) {
     alpha_op = WebGLImageConversion::kAlphaDoUnmultiply;
   }
 
-  // Use WebGLImageConversion to convert the data, if needed, and point
-  // `gl_data` at the temporary buffer `image_conversion_data`.
+  // If there are required conversions that Skia could not do above, then use
+  // WebGLImageConversion to convert the data, and point `gl_data` at the
+  // temporary buffer `image_conversion_data`.
   Vector<uint8_t> image_conversion_data;
-  if (params.type != GL_UNSIGNED_BYTE ||
-      WebGLImageConversion::SkColorTypeToDataFormat(pixmap->colorType()) !=
-          WebGLImageConversion::kDataFormatRGBA8 ||
-      params.format != GL_RGBA ||
+  if (WebGLImageConversion::SkColorTypeToDataFormat(pixmap.colorType()) !=
+          WebGLImageConversion::GetDataFormat(params.format, params.type) ||
       alpha_op != WebGLImageConversion::kAlphaDoNothing || do_flip_y ||
       selecting_sub_rectangle || params.depth != 1) {
-    // The UNSIGNED_INT_10F_11F_11F_REV type pack/unpack isn't implemented,
-    // use GL_FLOAT instead.
-    if (params.type == GL_UNSIGNED_INT_10F_11F_11F_REV)
-      params.type = GL_FLOAT;
-
     // Adjust the source image rectangle if doing a y-flip.
     gfx::Rect adjusted_source_rect(params.unpack_skip_pixels,
-                                   params.unpack_skip_rows, *params.width,
-                                   *params.height);
+                                   params.unpack_skip_rows,
+                                   params.width.value_or(pixmap.width()),
+                                   params.height.value_or(pixmap.height()));
     if (do_flip_y) {
-      adjusted_source_rect.set_y(pixmap->height() -
+      adjusted_source_rect.set_y(pixmap.height() -
                                  adjusted_source_rect.bottom());
     }
     if (!WebGLImageConversion::PackSkPixmap(
-            pixmap, params.format, params.type, do_flip_y, alpha_op,
-            adjusted_source_rect, *params.depth,
+            &pixmap, params.format, params.type, do_flip_y, alpha_op,
+            adjusted_source_rect, params.depth.value_or(1),
             /*source_unpack_alignment=*/0, params.unpack_image_height,
             image_conversion_data)) {
       SynthesizeGLError(GL_INVALID_VALUE, func_name, "packImage error");
@@ -5125,6 +5166,12 @@
 
   // Upload using GL.
   ScopedUnpackParametersResetRestore temporary_reset_unpack(this);
+  if (!params.width)
+    params.width = pixmap.width();
+  if (!params.height)
+    params.height = pixmap.height();
+  if (!params.depth)
+    params.depth = 1;
   TexImageBase(params, gl_data);
 }
 
@@ -5221,7 +5268,7 @@
   DCHECK_EQ(sk_image->width(), image->width());
   DCHECK_EQ(sk_image->height(), image->height());
 
-  TexImageSkImage(params, sk_image.get(), image_has_flip_y);
+  TexImageSkImage(params, std::move(sk_image), image_has_flip_y);
 }
 
 bool WebGLRenderingContextBase::ValidateTexFunc(
@@ -5479,7 +5526,8 @@
   }
 
   auto pixmap = pixels->GetSkPixmap();
-  TexImageSkPixmap(params, &pixmap, /*pixmap_has_flip_y=*/false);
+  auto image = SkImage::MakeFromRaster(pixmap, nullptr, nullptr);
+  TexImageSkImage(params, std::move(image), /*image_has_flip_y=*/false);
 }
 
 void WebGLRenderingContextBase::texImage2D(GLenum target,
@@ -5531,12 +5579,12 @@
   WebGLImageConversion::ImageExtractor image_extractor(
       image_for_render.get(), params.unpack_premultiply_alpha,
       unpack_colorspace_conversion_ == GL_NONE);
-  const SkImage* const sk_image = image_extractor.GetSkImage();
+  auto sk_image = image_extractor.GetSkImage();
   if (!sk_image) {
     SynthesizeGLError(GL_INVALID_VALUE, func_name, "bad image data");
     return;
   }
-  TexImageSkImage(params, sk_image, /*image_has_flip_y=*/false);
+  TexImageSkImage(params, std::move(sk_image), /*image_has_flip_y=*/false);
 }
 
 void WebGLRenderingContextBase::texImage2D(ExecutionContext* execution_context,
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
index 5af1d30..a271586 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -1203,12 +1203,10 @@
   // virtual because some state is only tracked in WebGL 2.
   virtual void GetCurrentUnpackState(TexImageParams& params);
 
+  // Upload `image` to the specified texture.
   void TexImageSkImage(TexImageParams params,
-                       const SkImage* image,
+                       sk_sp<SkImage> image,
                        bool image_has_flip_y);
-  void TexImageSkPixmap(TexImageParams params,
-                        const SkPixmap* pixmap,
-                        bool pixmap_has_flip_y);
 
   // Call the underlying Tex[Sub]Image{2D|3D} function. Always replace
   // `params.internalformat` with the result from ConvertTexInternalFormat.
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc b/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
index 2c35baa4..861cdb69 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
@@ -68,224 +68,227 @@
   return ClampFloat<T>(value * std::numeric_limits<T>::max());
 }
 
-// Return kDataFormatNumFormats if format/type combination is invalid.
-WebGLImageConversion::DataFormat GetDataFormat(GLenum destination_format,
-                                               GLenum destination_type) {
-  WebGLImageConversion::DataFormat dst_format =
-      WebGLImageConversion::kDataFormatRGBA8;
-  switch (destination_type) {
+}  // namespace
+
+WebGLImageConversion::DataFormat WebGLImageConversion::GetDataFormat(
+    GLenum format,
+    GLenum type) {
+  DataFormat result = kDataFormatRGBA8;
+  switch (type) {
     case GL_BYTE:
-      switch (destination_format) {
+      switch (format) {
         case GL_RED:
         case GL_RED_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatR8_S;
+          result = kDataFormatR8_S;
           break;
         case GL_RG:
         case GL_RG_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRG8_S;
+          result = kDataFormatRG8_S;
           break;
         case GL_RGB:
         case GL_RGB_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRGB8_S;
+          result = kDataFormatRGB8_S;
           break;
         case GL_RGBA:
         case GL_RGBA_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRGBA8_S;
+          result = kDataFormatRGBA8_S;
           break;
         default:
-          return WebGLImageConversion::kDataFormatNumFormats;
+          return kDataFormatNumFormats;
       }
       break;
     case GL_UNSIGNED_BYTE:
-      switch (destination_format) {
+      switch (format) {
         case GL_RGB:
         case GL_RGB_INTEGER:
         case GL_SRGB_EXT:
-          dst_format = WebGLImageConversion::kDataFormatRGB8;
+          result = kDataFormatRGB8;
           break;
         case GL_RGBA:
         case GL_RGBA_INTEGER:
         case GL_SRGB_ALPHA_EXT:
-          dst_format = WebGLImageConversion::kDataFormatRGBA8;
+          result = kDataFormatRGBA8;
           break;
         case GL_ALPHA:
-          dst_format = WebGLImageConversion::kDataFormatA8;
+          result = kDataFormatA8;
           break;
         case GL_LUMINANCE:
         case GL_RED:
         case GL_RED_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatR8;
+          result = kDataFormatR8;
           break;
         case GL_RG:
         case GL_RG_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRG8;
+          result = kDataFormatRG8;
           break;
         case GL_LUMINANCE_ALPHA:
-          dst_format = WebGLImageConversion::kDataFormatRA8;
+          result = kDataFormatRA8;
           break;
         default:
-          return WebGLImageConversion::kDataFormatNumFormats;
+          return kDataFormatNumFormats;
       }
       break;
     case GL_SHORT:
-      switch (destination_format) {
+      switch (format) {
         case GL_RED_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatR16_S;
+          result = kDataFormatR16_S;
           break;
         case GL_RG_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRG16_S;
+          result = kDataFormatRG16_S;
           break;
         case GL_RGB_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRGB16_S;
+          result = kDataFormatRGB16_S;
           break;
         case GL_RGBA_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRGBA16_S;
+          result = kDataFormatRGBA16_S;
           break;
         default:
-          return WebGLImageConversion::kDataFormatNumFormats;
+          return kDataFormatNumFormats;
       }
       break;
     case GL_UNSIGNED_SHORT:
-      switch (destination_format) {
+      switch (format) {
         case GL_RED_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatR16;
+          result = kDataFormatR16;
           break;
         case GL_DEPTH_COMPONENT:
-          dst_format = WebGLImageConversion::kDataFormatD16;
+          result = kDataFormatD16;
           break;
         case GL_RG_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRG16;
+          result = kDataFormatRG16;
           break;
         case GL_RGB_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRGB16;
+          result = kDataFormatRGB16;
           break;
         case GL_RGBA_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRGBA16;
+          result = kDataFormatRGBA16;
           break;
         default:
-          return WebGLImageConversion::kDataFormatNumFormats;
+          return kDataFormatNumFormats;
       }
       break;
     case GL_INT:
-      switch (destination_format) {
+      switch (format) {
         case GL_RED_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatR32_S;
+          result = kDataFormatR32_S;
           break;
         case GL_RG_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRG32_S;
+          result = kDataFormatRG32_S;
           break;
         case GL_RGB_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRGB32_S;
+          result = kDataFormatRGB32_S;
           break;
         case GL_RGBA_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRGBA32_S;
+          result = kDataFormatRGBA32_S;
           break;
         default:
-          return WebGLImageConversion::kDataFormatNumFormats;
+          return kDataFormatNumFormats;
       }
       break;
     case GL_UNSIGNED_INT:
-      switch (destination_format) {
+      switch (format) {
         case GL_RED_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatR32;
+          result = kDataFormatR32;
           break;
         case GL_DEPTH_COMPONENT:
-          dst_format = WebGLImageConversion::kDataFormatD32;
+          result = kDataFormatD32;
           break;
         case GL_RG_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRG32;
+          result = kDataFormatRG32;
           break;
         case GL_RGB_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRGB32;
+          result = kDataFormatRGB32;
           break;
         case GL_RGBA_INTEGER:
-          dst_format = WebGLImageConversion::kDataFormatRGBA32;
+          result = kDataFormatRGBA32;
           break;
         default:
-          return WebGLImageConversion::kDataFormatNumFormats;
+          return kDataFormatNumFormats;
       }
       break;
     case GL_HALF_FLOAT_OES:  // OES_texture_half_float
     case GL_HALF_FLOAT:
-      switch (destination_format) {
+      switch (format) {
         case GL_RGBA:
-          dst_format = WebGLImageConversion::kDataFormatRGBA16F;
+          result = kDataFormatRGBA16F;
           break;
         case GL_RGB:
-          dst_format = WebGLImageConversion::kDataFormatRGB16F;
+          result = kDataFormatRGB16F;
           break;
         case GL_RG:
-          dst_format = WebGLImageConversion::kDataFormatRG16F;
+          result = kDataFormatRG16F;
           break;
         case GL_ALPHA:
-          dst_format = WebGLImageConversion::kDataFormatA16F;
+          result = kDataFormatA16F;
           break;
         case GL_LUMINANCE:
         case GL_RED:
-          dst_format = WebGLImageConversion::kDataFormatR16F;
+          result = kDataFormatR16F;
           break;
         case GL_LUMINANCE_ALPHA:
-          dst_format = WebGLImageConversion::kDataFormatRA16F;
+          result = kDataFormatRA16F;
           break;
         default:
-          return WebGLImageConversion::kDataFormatNumFormats;
+          return kDataFormatNumFormats;
       }
       break;
     case GL_FLOAT:  // OES_texture_float
-      switch (destination_format) {
+      switch (format) {
         case GL_RGBA:
-          dst_format = WebGLImageConversion::kDataFormatRGBA32F;
+          result = kDataFormatRGBA32F;
           break;
         case GL_RGB:
-          dst_format = WebGLImageConversion::kDataFormatRGB32F;
+          result = kDataFormatRGB32F;
           break;
         case GL_RG:
-          dst_format = WebGLImageConversion::kDataFormatRG32F;
+          result = kDataFormatRG32F;
           break;
         case GL_ALPHA:
-          dst_format = WebGLImageConversion::kDataFormatA32F;
+          result = kDataFormatA32F;
           break;
         case GL_LUMINANCE:
         case GL_RED:
-          dst_format = WebGLImageConversion::kDataFormatR32F;
+          result = kDataFormatR32F;
           break;
         case GL_DEPTH_COMPONENT:
-          dst_format = WebGLImageConversion::kDataFormatD32F;
+          result = kDataFormatD32F;
           break;
         case GL_LUMINANCE_ALPHA:
-          dst_format = WebGLImageConversion::kDataFormatRA32F;
+          result = kDataFormatRA32F;
           break;
         default:
-          return WebGLImageConversion::kDataFormatNumFormats;
+          return kDataFormatNumFormats;
       }
       break;
     case GL_UNSIGNED_SHORT_4_4_4_4:
-      dst_format = WebGLImageConversion::kDataFormatRGBA4444;
+      result = kDataFormatRGBA4444;
       break;
     case GL_UNSIGNED_SHORT_5_5_5_1:
-      dst_format = WebGLImageConversion::kDataFormatRGBA5551;
+      result = kDataFormatRGBA5551;
       break;
     case GL_UNSIGNED_SHORT_5_6_5:
-      dst_format = WebGLImageConversion::kDataFormatRGB565;
+      result = kDataFormatRGB565;
       break;
     case GL_UNSIGNED_INT_5_9_9_9_REV:
-      dst_format = WebGLImageConversion::kDataFormatRGB5999;
+      result = kDataFormatRGB5999;
       break;
     case GL_UNSIGNED_INT_24_8:
-      dst_format = WebGLImageConversion::kDataFormatDS24_8;
+      result = kDataFormatDS24_8;
       break;
     case GL_UNSIGNED_INT_10F_11F_11F_REV:
-      dst_format = WebGLImageConversion::kDataFormatRGB10F11F11F;
+      result = kDataFormatRGB10F11F11F;
       break;
     case GL_UNSIGNED_INT_2_10_10_10_REV:
-      dst_format = WebGLImageConversion::kDataFormatRGBA2_10_10_10;
+      result = kDataFormatRGBA2_10_10_10;
       break;
     default:
-      return WebGLImageConversion::kDataFormatNumFormats;
+      return kDataFormatNumFormats;
   }
-  return dst_format;
+  return result;
 }
 
+namespace {
+
 // The following Float to Half-Float conversion code is from the implementation
 // of http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf , "Fast Half
 // Float Conversions" by Jeroen van der Zijp, November 2008 (Revised September
@@ -3539,6 +3542,26 @@
   }
 }
 
+SkColorType WebGLImageConversion::DataFormatToSkColorType(
+    WebGLImageConversion::DataFormat data_format,
+    SkColorType default_color_type) {
+  switch (data_format) {
+    case kDataFormatRGBA8:
+      return kRGBA_8888_SkColorType;
+    case kDataFormatBGRA8:
+      return kBGRA_8888_SkColorType;
+    case kDataFormatRGBA16:
+      return kR16G16B16A16_unorm_SkColorType;
+    case kDataFormatRGBA16F:
+      return kRGBA_F16_SkColorType;
+    case kDataFormatRGBA32F:
+      return kRGBA_F32_SkColorType;
+    default:
+      break;
+  }
+  return default_color_type;
+}
+
 bool WebGLImageConversion::ComputeFormatAndTypeParameters(
     GLenum format,
     GLenum type,
@@ -3917,80 +3940,6 @@
                     flip_y);
 }
 
-bool WebGLImageConversion::PackImageData(
-    Image* image,
-    const void* pixels,
-    GLenum format,
-    GLenum type,
-    bool flip_y,
-    AlphaOp alpha_op,
-    DataFormat source_format,
-    unsigned source_image_width,
-    unsigned source_image_height,
-    const gfx::Rect& source_image_sub_rectangle,
-    int depth,
-    unsigned source_unpack_alignment,
-    int unpack_image_height,
-    Vector<uint8_t>& data) {
-  if (!pixels)
-    return false;
-
-  unsigned packed_size;
-  // Output data is tightly packed (alignment == 1).
-  PixelStoreParams params;
-  params.alignment = 1;
-  if (ComputeImageSizeInBytes(format, type, source_image_sub_rectangle.width(),
-                              source_image_sub_rectangle.height(), depth,
-                              params, &packed_size, nullptr,
-                              nullptr) != GL_NO_ERROR)
-    return false;
-  data.resize(packed_size);
-
-  return PackPixels(reinterpret_cast<const uint8_t*>(pixels), source_format,
-                    source_image_width, source_image_height,
-                    source_image_sub_rectangle, depth, source_unpack_alignment,
-                    unpack_image_height, format, type, alpha_op, data.data(),
-                    flip_y);
-}
-
-bool WebGLImageConversion::ExtractImageData(
-    const void* image_data,
-    DataFormat source_data_format,
-    const gfx::Size& image_data_size,
-    const gfx::Rect& source_image_sub_rectangle,
-    int depth,
-    int unpack_image_height,
-    GLenum format,
-    GLenum type,
-    bool flip_y,
-    bool premultiply_alpha,
-    Vector<uint8_t>& data) {
-  if (!image_data)
-    return false;
-  int width = image_data_size.width();
-  int height = image_data_size.height();
-
-  unsigned packed_size;
-  // Output data is tightly packed (alignment == 1).
-  PixelStoreParams params;
-  params.alignment = 1;
-  if (ComputeImageSizeInBytes(format, type, source_image_sub_rectangle.width(),
-                              source_image_sub_rectangle.height(), depth,
-                              params, &packed_size, nullptr,
-                              nullptr) != GL_NO_ERROR)
-    return false;
-  data.resize(packed_size);
-
-  if (!PackPixels(image_data, source_data_format, width, height,
-                  source_image_sub_rectangle, depth, 0, unpack_image_height,
-                  format, type,
-                  premultiply_alpha ? kAlphaDoPremultiply : kAlphaDoNothing,
-                  data.data(), flip_y))
-    return false;
-
-  return true;
-}
-
 bool WebGLImageConversion::ExtractTextureData(
     unsigned width,
     unsigned height,
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h b/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h
index 483b6f6..a17f3fd 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h
@@ -130,12 +130,21 @@
     ImageExtractor(const ImageExtractor&) = delete;
     ImageExtractor& operator=(const ImageExtractor&) = delete;
 
-    const SkImage* GetSkImage() { return sk_image_.get(); }
+    sk_sp<SkImage> GetSkImage() { return sk_image_; }
 
    private:
     sk_sp<SkImage> sk_image_;
   };
 
+  // Convert a GL format and GL type to a DataFormat. This will return
+  // kDataFormatNumFormats if combination is invalid.
+  static DataFormat GetDataFormat(GLenum format, GLenum type);
+
+  // Convert a DataFormat to an SkColorType. If there is no exactly matching
+  // SkColorType, return the specified `default_color_type`.
+  static SkColorType DataFormatToSkColorType(DataFormat data_format,
+                                             SkColorType default_color_type);
+
   // Convert an SkColorType to the most appropriate DataFormat.
   static DataFormat SkColorTypeToDataFormat(SkColorType color_type);
 
diff --git a/third_party/blink/renderer/platform/heap/BUILD.gn b/third_party/blink/renderer/platform/heap/BUILD.gn
index 24b76984..4496905 100644
--- a/third_party/blink/renderer/platform/heap/BUILD.gn
+++ b/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -116,6 +116,7 @@
   if (is_android) {
     deps += [
       "//base:base_java",
+      "//build/android:build_java",
       "//content/shell/android:content_shell_assets",
       "//net/android:net_java",
       "//ui/android:ui_full_java",
@@ -184,6 +185,7 @@
   if (is_android) {
     deps += [
       "//base:base_java",
+      "//build/android:build_java",
       "//content/shell/android:content_shell_assets",
       "//net/android:net_java",
       "//ui/android:ui_full_java",
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index 6b305c8..b78a6f0 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -158,6 +158,8 @@
 crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-039.html [ Failure ]
 crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-040.html [ Failure ]
 crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-047.html [ Failure ]
+crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-048.html [ Failure ]
+crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-049.html [ Failure ]
 crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-row-flex-fragmentation-007.html [ Failure ]
 crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-row-flex-fragmentation-008.html [ Failure ]
 crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-row-flex-fragmentation-010.html [ Failure ]
@@ -216,6 +218,8 @@
 crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-044.html [ Failure ]
 crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-045.html [ Failure ]
 crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-046.html [ Failure ]
+crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-050.html [ Failure ]
+crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-054.html [ Failure ]
 crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-008.html [ Failure ]
 crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-014.html [ Failure ]
 crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-015.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index f8d1c6e..f9ee3b82 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3381,9 +3381,7 @@
 crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
-crbug.com/626703 [ Mac10.12 ] virtual/document-transition/wpt_internal/document-transition/one-element-two-targets.html [ Failure ]
 crbug.com/626703 [ Mac10.12 ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/navigate-ancestor-nested-fenced-frame.https.html [ Timeout ]
-crbug.com/626703 [ Mac11 ] virtual/document-transition/wpt_internal/document-transition/one-element-two-targets.html [ Failure ]
 crbug.com/626703 [ Mac11-arm64 ] external/wpt/fetch/private-network-access/redirect.https.window.html [ Timeout ]
 crbug.com/626703 [ Mac11-arm64 ] external/wpt/fetch/private-network-access/shared-worker.https.window.html [ Timeout ]
 crbug.com/626703 [ Win10.20h2 ] external/wpt/permissions-policy/reporting/xr-report-only.https.html [ Crash ]
@@ -3428,7 +3426,6 @@
 crbug.com/626703 [ Mac11-arm64 ] external/wpt/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-unicode.html?wpt_flags=h2 [ Failure Timeout ]
 crbug.com/626703 [ Mac11-arm64 ] external/wpt/websockets/interfaces/WebSocket/send/009.html?wpt_flags=h2 [ Timeout ]
 crbug.com/626703 [ Mac11 ] external/wpt/focus/activeelement-after-focusing-different-site-iframe-then-immediately-focusing-back.html [ Failure Timeout ]
-crbug.com/626703 [ Mac10.15 ] virtual/document-transition/wpt_internal/document-transition/one-element-two-targets.html [ Failure ]
 crbug.com/626703 external/wpt/scroll-to-text-fragment/scroll-to-text-fragment.html [ Failure Skip Timeout ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/service-workers/service-worker/same-site-cookies.https.html [ Skip Timeout ]
 crbug.com/626703 [ Mac10.12 ] external/wpt/signed-exchange/subresource/sxg-subresource-header-integrity-mismatch.tentative.html [ Timeout ]
@@ -6005,9 +6002,6 @@
 crbug.com/1032451 virtual/threaded-no-composited-antialiasing/animations/stability/animation-iteration-event-destroy-renderer.html [ Pass Timeout ]
 crbug.com/931646 [ Mac ] http/tests/preload/meta-viewport-link-headers-imagesrcset.html [ Failure Pass ]
 
-crbug.com/1303648 external/wpt/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/in-order.html [ Timeout ]
-crbug.com/1317437 external/wpt/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/delay-load-event-2.html [ Failure ]
-
 # These tests will only run in the virtual test suite where the frequency
 # capping for overlay popup detection is disabled. This eliminates the need
 # for waitings in web tests to trigger a detection event.
@@ -7605,10 +7599,6 @@
 crbug.com/1248581 fast/scrolling/resize-corner-tracking-touch.html [ Failure Pass ]
 crbug.com/1312036 virtual/hidpi/fast/scrolling/scrollbars/dsf-ready/mouse-interactions-dsf-2.html [ Failure Pass ]
 
-# Sheriff 2022-03-29
-crbug.com/1311138 [ Mac10.13 ] virtual/document-transition/wpt_internal/document-transition/one-element-two-targets.html [ Skip ]
-crbug.com/1311138 [ Mac10.14 ] virtual/document-transition/wpt_internal/document-transition/one-element-two-targets.html [ Skip ]
-
 # These tests fail on SwiftShader FEMU due to a change in log/exp implementation.
 crbug.com/1311456 [ Fuchsia ] fast/css3-text/css3-text-decoration/text-decoration-style-inherit.html [ Skip ]
 crbug.com/1311456 [ Fuchsia ] tables/mozilla/core/bloomberg.html [ Skip ]
@@ -7732,7 +7722,6 @@
 crbug.com/1267538 [ Mac ] http/tests/csspaint/border-color.html [ Failure Pass ]
 
 # Sheriff 2022-04-26
-crbug.com/1320119 [ Mac10.13 ] external/wpt/mediasession/idlharness.window.html [ Failure Pass Timeout ]
 crbug.com/1320120 [ Mac10.13 ] fast/harness/perftests/runs-per-second-log.html [ Failure Pass Timeout ]
 crbug.com/1320121 [ Mac10.13 ] http/tests/inspector-protocol/network/blocked-setcookie-same-party-cross-party.js [ Failure Pass Timeout ]
 crbug.com/1320140 [ Win ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/disallowed-navigations.https.html [ Pass Timeout ]
@@ -7740,3 +7729,6 @@
 crbug.com/1320140 [ Win ] virtual/fenced-frame-shadow-dom/wpt_internal/fenced_frame/disallowed-navigations.https.html [ Pass Timeout ]
 crbug.com/1320140 [ Win ] virtual/fenced-frame-shadow-dom/wpt_internal/fenced_frame/opaque-ad-sizes.https.html [ Pass Timeout ]
 crbug.com/1288741 external/wpt/scroll-to-text-fragment/find-range-from-text-directive.html [ Pass Timeout ]
+
+# Sheriff 2022-04-27
+crbug.com/1320418 [ Win7 ] external/wpt/dom/nodes/Document-createEvent.https.html [ Failure ]
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-048.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-048.html
new file mode 100644
index 0000000..8280041
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-048.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>
+  Tests that a flex-item that shrinks *doesn't* expand.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+  <div style="display: flex; flex-direction: column; flex-wrap: wrap; height: 200px;">
+    <div style="background: green; flex-basis: fit-content; height: 10px; width: 25px;">
+      <div style="contain: size; width: 25px; height: 50px;"></div>
+      <div style="contain: size; width: 25px; height: 100px;"></div>
+    </div>
+    <div style="background: green; width: 25px; height: 50px;"></div>
+    <div style="background: green; flex-basis: min-content; height: 10px; width: 25px;">
+      <div style="contain: size; width: 25px; height: 50px;"></div>
+      <div style="contain: size; width: 25px; height: 100px;"></div>
+    </div>
+    <div style="background: green; width: 25px; height: 50px;"></div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-049.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-049.html
new file mode 100644
index 0000000..0ede74a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-049.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>
+  Tests that a flex-item with an indefinite flex-basis expands if the
+  container hieght is auto.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+  <div style="display: flex; flex-direction: column;">
+    <div style="background: green; flex-basis: content; height: 10px;">
+      <div style="contain: size; width: 50px; height: 50px;"></div>
+      <div style="contain: size; width: 50px; height: 100px;"></div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-050.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-050.html
new file mode 100644
index 0000000..ae683e93
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-050.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>
+  Tests that a flex-item with an indefinite flex-basis expands if the
+  container height is auto.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+  <div style="display: flex; flex-direction: column;">
+    <div style="background: green; flex-basis: content; height: 10px;">
+      <div style="contain: size; width: 50px; height: 50px;"></div>
+      <div style="contain: size; width: 50px; height: 100px;"></div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-051.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-051.html
new file mode 100644
index 0000000..9fc2a6e4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-051.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>
+  Tests that a flex-item with a definite flex-basis *doesn't* expand.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+  <div style="display: flex; flex-direction: column;">
+    <div style="background: green; flex-basis: 10px; height: 10px;">
+      <div style="contain: size; width: 50px; height: 50px;"></div>
+      <div style="contain: size; width: 50px; height: 100px;"></div>
+    </div>
+    <div style="background: green; width: 50px; height: 190px;"></div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-052.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-052.html
new file mode 100644
index 0000000..faa0d130
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-052.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>
+  Tests that a flex-item with an definite flex-basis but an indefinite height expands.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+  <div style="display: flex; flex-direction: column;">
+    <div style="background: green; flex-basis: 10px;">
+      <div style="contain: size; width: 50px; height: 50px;"></div>
+      <div style="contain: size; width: 50px; height: 100px;"></div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-053.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-053.html
new file mode 100644
index 0000000..524870e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-053.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>
+  Tests that a flex-item that can't shrink and has a definite flex-basis, an
+  indefinite height, and a non-auto min-height *doesn't* expand.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+  <div style="display: flex; flex-direction: column; height: 100px;">
+    <div style="background: green; flex-basis: 10px; min-height: 10px;">
+      <div style="contain: size; width: 50px; height: 50px;"></div>
+      <div style="contain: size; width: 50px; height: 100px;"></div>
+    </div>
+    <div style="background: green; width: 50px; height: 190px;"></div>
+  </div>
+  <div style="background: green; width: 50px; height: 100px;"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-054.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-054.html
new file mode 100644
index 0000000..60c130e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-054.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>
+  Tests that a flex-item with an definite flex-basis, an indefinite height, and
+  a non-auto min-height does expand.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+  <div style="display: flex; flex-direction: column;">
+    <div style="background: green; flex-basis: 10px; min-height: 10px;">
+      <div style="contain: size; width: 50px; height: 50px;"></div>
+      <div style="contain: size; width: 50px; height: 100px;"></div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-055.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-055.html
new file mode 100644
index 0000000..2958e616
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-055.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>
+  Tests that a flex-item with an definite flex-basis, an indefinite height, and
+  can't shrink does expand.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+  <div style="display: flex; flex-direction: column;">
+    <div style="background: green; flex-basis: 10px; justify-self: flex-start;">
+      <div style="contain: size; width: 50px; height: 50px;"></div>
+      <div style="contain: size; width: 50px; height: 100px;"></div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-008.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-008.html
index 562cb61..dfade0f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-008.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-008.html
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <title>
-  Tests that a flex-item with a fixed block-size container grows due to fragmentation.
+  Tests that a flex-item with a fixed block-size container *doesn't* grow due to fragmentation
+  if stretched.
 </title>
 <link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
 <link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
@@ -12,4 +13,5 @@
       <div style="display: inline-block; width: 50px; height: 100px;"></div>
     </div>
   </div>
+  <div style="background: green; width: 50px; height: 100px;"></div>
 </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-009.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-009.html
index b51c7883..8dbaa692 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-009.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-009.html
@@ -8,7 +8,7 @@
 <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <div style="width: 100px; height: 100px; columns: 2; column-gap: 0; column-fill: auto; background: red;">
   <div style="display: flex; background: green;">
-    <div style="display: flex;">
+    <div style="display: flex; align-self: flex-start;">
       <div style="line-height: 0;">
         <div style="display: inline-block; width: 50px; height: 50px;"></div>
         <div style="display: inline-block; width: 50px; height: 100px;"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-painting-003.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-painting-003.html
index 89a27937..e4f061f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-painting-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-painting-003.html
@@ -23,8 +23,7 @@
         Decoration paints are ordered by text-decoration-line
         (underline, overline, text, line-through), then by highlight
         overlay (originating, ::grammar-error, ::spelling-error,
-        ::target-text, ::selection). See options (d, d, d) in
-        csswg-drafts#6022 for more details.
+        ::target-text, ::selection).
     */
     * {
         text-decoration-skip-ink: none;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-painting-004.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-painting-004.html
index 7abccb5..26ded65 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-painting-004.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-painting-004.html
@@ -24,8 +24,7 @@
         Decoration paints are ordered by text-decoration-line
         (underline, overline, text, line-through), then by highlight
         overlay (originating, ::grammar-error, ::spelling-error,
-        ::target-text, ::selection). See options (d, d, d) in
-        csswg-drafts#6022 for more details.
+        ::target-text, ::selection).
     */
     * {
         text-decoration-skip-ink: none;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-004.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-004.html
similarity index 91%
rename from third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-004.tentative.html
rename to third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-004.html
index cc1d4da..61e2b7d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-004.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-004.html
@@ -1,6 +1,5 @@
 <!doctype html>
 <meta charset="utf-8">
-<!-- tentative due to unresolved spec issue: see question 3 in <https://github.com/w3c/csswg-drafts/issues/6386> -->
 <title>CSS Pseudo-Elements Test: paired cascade: rule includes highlight pseudos other than ::selection</title>
 <link rel="author" name="Delan Azabani" href="mailto:dazabani@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#highlight-cascade">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-005.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-005.html
similarity index 92%
rename from third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-005.tentative.html
rename to third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-005.html
index 4d402292..50677c8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-005.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/highlight-paired-cascade-005.html
@@ -1,6 +1,5 @@
 <!doctype html>
 <meta charset="utf-8">
-<!-- tentative due to unresolved spec issue: see question 6 in <https://github.com/w3c/csswg-drafts/issues/6386> -->
 <title>CSS Pseudo-Elements Test: paired cascade: UA default highlight colors are not used when highlight pseudo has declared color value of unset</title>
 <link rel="author" name="Delan Azabani" href="mailto:dazabani@igalia.com">
 <link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#highlight-cascade">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/textpath-selection-011-ref.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/textpath-selection-011-ref.html
index 6950c32..6d07c71 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/textpath-selection-011-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/textpath-selection-011-ref.html
@@ -15,7 +15,6 @@
       /*
       color suppresses UA default background-color,
       but fill and stroke do not, so set explicitly
-      https://github.com/w3c/csswg-drafts/issues/6386
       */
       fill: green;
       /*
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/textpath-selection-011.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/textpath-selection-011.html
index 3d72548..1e84519 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/textpath-selection-011.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/textpath-selection-011.html
@@ -21,7 +21,6 @@
       /*
       color suppresses UA default background-color,
       but fill and stroke do not, so set explicitly
-      https://github.com/w3c/csswg-drafts/issues/6386
       */
       fill: green;
       /*
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/message-channels/detached-iframe.window.js b/third_party/blink/web_tests/external/wpt/webmessaging/message-channels/detached-iframe.window.js
new file mode 100644
index 0000000..c1effaf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webmessaging/message-channels/detached-iframe.window.js
@@ -0,0 +1,47 @@
+// META: title=MessageChannel in a detached iframe test
+// META: script=/service-workers/service-worker/resources/test-helpers.sub.js
+// Pull in the with_iframe helper function from the service worker tests
+
+
+const IframeAction = {
+  REMOVE_BEFORE_CREATION: 'remove-before-creation',
+  REMOVE_AFTER_CREATION: 'remove-after-creation',
+};
+
+async function detached_frame_test(t, action) {
+  const iframe = await with_iframe('about:blank');
+  const iframe_MessageChannel = iframe.contentWindow.MessageChannel;
+
+  if (action === IframeAction.REMOVE_BEFORE_CREATION) {
+    iframe.remove();
+  }
+
+  (() => {
+    const mc = new iframe_MessageChannel();
+    mc.port1.postMessage("boo");
+    mc.port2.onmessage = t.unreached_func("message event received");
+    mc.port2.onmessageerror = t.unreached_func("message event received");
+  })();
+
+  if (action === IframeAction.REMOVE_AFTER_CREATION) {
+    iframe.remove();
+  }
+
+  // TODO(https://github.com/web-platform-tests/wpt/issues/7899): Change to
+  // some sort of cross-browser GC trigger.
+  if (self.gc) self.gc();
+
+  // We are testing that neither of the above two events fire. We assume that a 2 second timeout
+  // is good enough. We can't use any other API for an end condition because each MessagePort has
+  // its own independent port message queue, which has no ordering guarantees relative to other
+  // APIs.
+  await new Promise(resolve => t.step_timeout(resolve, 2000));
+}
+
+promise_test(async (t) => {
+  return detached_frame_test(t, IframeAction.REMOVE_AFTER_CREATION);
+}, 'MessageChannel created from a detached iframe should not send messages (remove after create)');
+
+promise_test(async (t) => {
+  return detached_frame_test(t, IframeAction.REMOVE_BEFORE_CREATION);
+}, 'MessageChannel created from a detached iframe should not send messages (remove before create)');
diff --git a/third_party/blink/web_tests/wpt_internal/document-transition/one-element-two-targets.html b/third_party/blink/web_tests/wpt_internal/document-transition/one-element-two-targets.html
index 15c3a5b..628e5382 100644
--- a/third_party/blink/web_tests/wpt_internal/document-transition/one-element-two-targets.html
+++ b/third_party/blink/web_tests/wpt_internal/document-transition/one-element-two-targets.html
@@ -17,6 +17,7 @@
   background: pink;
   width: 10px;
   height: 10px;
+  page-transition-tag: hidden;
 }
 .target {
   width: 100px;
@@ -58,8 +59,6 @@
 <script>
 async function runTest() {
   let t = document.createDocumentTransition();
-  t.setElement(hidden, "hidden");
-
   t.setElement(from, "target1");
   t.setElement(from, "target2");
   t.start(() => {
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/PRESUBMIT.py b/third_party/blink/web_tests/wpt_internal/prerender/PRESUBMIT.py
index fe8f789..4ce4d7b 100644
--- a/third_party/blink/web_tests/wpt_internal/prerender/PRESUBMIT.py
+++ b/third_party/blink/web_tests/wpt_internal/prerender/PRESUBMIT.py
@@ -38,7 +38,7 @@
         if not _CheckFileTimeoutMetaTags(f):
             results.append(
                 output_api.PresubmitError(
-                    ('Missing long timeout.'
+                    ('Missing long timeout. '
                      'Add `<meta name="timeout" content="long">` to %s.') %
                     f.LocalPath()))
     return results
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-cross-origin-subframe-navigation.html b/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-cross-origin-subframe-navigation.html
index 205d7bd..eabfd2f 100644
--- a/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-cross-origin-subframe-navigation.html
+++ b/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-cross-origin-subframe-navigation.html
@@ -13,6 +13,7 @@
   (https://crbug.com/1222551)
 -->
 <title>unload event handlers</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/unload-utils.js"></script>
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-main-frame-navigation.html b/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-main-frame-navigation.html
index 3055a0fa..2cc6401 100644
--- a/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-main-frame-navigation.html
+++ b/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-main-frame-navigation.html
@@ -13,6 +13,7 @@
   (https://crbug.com/1222551)
 -->
 <title>unload event handlers</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/unload-utils.js"></script>
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-remove-subframe.html b/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-remove-subframe.html
index 20e0528c..a79ba22 100644
--- a/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-remove-subframe.html
+++ b/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-remove-subframe.html
@@ -9,6 +9,7 @@
   (https://crbug.com/1222551)
 -->
 <title>unload event handlers</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/unload-utils.js"></script>
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-same-origin-subframe-navigation.html b/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-same-origin-subframe-navigation.html
index 8bb0564..d884c56 100644
--- a/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-same-origin-subframe-navigation.html
+++ b/third_party/blink/web_tests/wpt_internal/prerender/unload-on-prerender-same-origin-subframe-navigation.html
@@ -9,6 +9,7 @@
   (https://crbug.com/1222551)
 -->
 <title>unload event handlers</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/unload-utils.js"></script>
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html
index 73ffb23..1d3d50a 100644
--- a/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/cts.https.html
@@ -2797,6 +2797,9 @@
 <meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,all:bool:*'>
 <meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,any:bool:*'>
 <meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,arrayLength:array:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asin:abstract_float:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asin:f32:*'>
+<meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,asin:f16:*'>
 <meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan:abstract_float:*'>
 <meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan:f32:*'>
 <meta name=variant content='?q=webgpu:shader,execution,expression,call,builtin,atan:f16:*'>
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index ca0d732d..b777df8 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-12-0-15-ged4d0710f
-Revision: ed4d0710f14878b51ce1885e0f3221e2d6d97a5a
+Version: VER-2-12-0-16-g6fb7b7a09
+Revision: 6fb7b7a09dfe348fefb16d163dc9d91f7503f1f6
 CPEPrefix: cpe:/a:freetype:freetype:2.11.1
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
diff --git a/third_party/inspector_protocol/README.chromium b/third_party/inspector_protocol/README.chromium
index 7fc11dd..e1c5b32 100644
--- a/third_party/inspector_protocol/README.chromium
+++ b/third_party/inspector_protocol/README.chromium
@@ -2,7 +2,7 @@
 Short Name: inspector_protocol
 URL: https://chromium.googlesource.com/deps/inspector_protocol/
 Version: 0
-Revision: bc288fbcde436fb15ebd1bbe98bd3710588d3341
+Revision: 0187bc7f0ccb1e78330843c50e3d7c7d6b9ef9f2
 License: BSD
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/inspector_protocol/check_protocol_compatibility.py b/third_party/inspector_protocol/check_protocol_compatibility.py
index d2df244..bcbd0c33 100755
--- a/third_party/inspector_protocol/check_protocol_compatibility.py
+++ b/third_party/inspector_protocol/check_protocol_compatibility.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright (c) 2011 Google Inc. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
diff --git a/third_party/inspector_protocol/code_generator.py b/third_party/inspector_protocol/code_generator.py
index df76716..f7c110a 100755
--- a/third_party/inspector_protocol/code_generator.py
+++ b/third_party/inspector_protocol/code_generator.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # 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.
diff --git a/third_party/inspector_protocol/concatenate_protocols.py b/third_party/inspector_protocol/concatenate_protocols.py
index 42ecc7f9..a2e8694 100755
--- a/third_party/inspector_protocol/concatenate_protocols.py
+++ b/third_party/inspector_protocol/concatenate_protocols.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # 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.
diff --git a/third_party/inspector_protocol/convert_protocol_to_json.py b/third_party/inspector_protocol/convert_protocol_to_json.py
index 7070a80..8370c53 100755
--- a/third_party/inspector_protocol/convert_protocol_to_json.py
+++ b/third_party/inspector_protocol/convert_protocol_to_json.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # 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.
diff --git a/third_party/inspector_protocol/crdtp/dispatch.cc b/third_party/inspector_protocol/crdtp/dispatch.cc
index d6bcabe4..aaae01f 100644
--- a/third_party/inspector_protocol/crdtp/dispatch.cc
+++ b/third_party/inspector_protocol/crdtp/dispatch.cc
@@ -78,6 +78,14 @@
   return result;
 }
 
+// static
+DispatchResponse DispatchResponse::SessionNotFound(std::string message) {
+  DispatchResponse result;
+  result.code_ = DispatchCode::SESSION_NOT_FOUND;
+  result.message_ = std::move(message);
+  return result;
+}
+
 // =============================================================================
 // Dispatchable - a shallow parser for CBOR encoded DevTools messages
 // =============================================================================
diff --git a/third_party/inspector_protocol/crdtp/dispatch.h b/third_party/inspector_protocol/crdtp/dispatch.h
index ac67fac..aed98d10 100644
--- a/third_party/inspector_protocol/crdtp/dispatch.h
+++ b/third_party/inspector_protocol/crdtp/dispatch.h
@@ -38,6 +38,7 @@
   INVALID_PARAMS = -32602,
   INTERNAL_ERROR = -32603,
   SERVER_ERROR = -32000,
+  SESSION_NOT_FOUND = SERVER_ERROR - 1,
 };
 
 // Information returned by command handlers. Usually returned after command
@@ -76,6 +77,10 @@
   // Used for application level errors, e.g. within protocol agents.
   static DispatchResponse ServerError(std::string message);
 
+  // Indicate that session with the id specified in the protocol message
+  // was not found (e.g. because it has already been detached).
+  static DispatchResponse SessionNotFound(std::string message);
+
  private:
   DispatchResponse() = default;
   DispatchCode code_;
diff --git a/third_party/inspector_protocol/crdtp/dispatch_test.cc b/third_party/inspector_protocol/crdtp/dispatch_test.cc
index 16c55de4..949867b 100644
--- a/third_party/inspector_protocol/crdtp/dispatch_test.cc
+++ b/third_party/inspector_protocol/crdtp/dispatch_test.cc
@@ -27,6 +27,13 @@
   EXPECT_EQ("Oops!", error.Message());
 }
 
+TEST(DispatchResponseTest, SessionNotFound) {
+  DispatchResponse error = DispatchResponse::SessionNotFound("OMG!");
+  EXPECT_FALSE(error.IsSuccess());
+  EXPECT_EQ(DispatchCode::SESSION_NOT_FOUND, error.Code());
+  EXPECT_EQ("OMG!", error.Message());
+}
+
 TEST(DispatchResponseTest, InternalError) {
   DispatchResponse error = DispatchResponse::InternalError();
   EXPECT_FALSE(error.IsSuccess());
diff --git a/third_party/netty-tcnative/BUILD.gn b/third_party/netty-tcnative/BUILD.gn
index eeb03ad..b3a43fa 100644
--- a/third_party/netty-tcnative/BUILD.gn
+++ b/third_party/netty-tcnative/BUILD.gn
@@ -43,5 +43,8 @@
     "src/java/io/netty/internal/tcnative/SSLContext.java",
     "src/java/io/netty/internal/tcnative/SessionTicketKey.java",
   ]
-  deps = [ "//base:base_java" ]
+  deps = [
+    "//base:base_java",
+    "//build/android:build_java",
+  ]
 }
diff --git a/third_party/webgpu-cts/ts_sources.txt b/third_party/webgpu-cts/ts_sources.txt
index c34eee2c..2673f40 100644
--- a/third_party/webgpu-cts/ts_sources.txt
+++ b/third_party/webgpu-cts/ts_sources.txt
@@ -273,6 +273,7 @@
 src/webgpu/shader/execution/expression/call/builtin/all.spec.ts
 src/webgpu/shader/execution/expression/call/builtin/any.spec.ts
 src/webgpu/shader/execution/expression/call/builtin/arrayLength.spec.ts
+src/webgpu/shader/execution/expression/call/builtin/asin.spec.ts
 src/webgpu/shader/execution/expression/call/builtin/atan.spec.ts
 src/webgpu/shader/execution/expression/call/builtin/atan2.spec.ts
 src/webgpu/shader/execution/expression/call/builtin/ceil.spec.ts
diff --git a/tools/android/audio_focus_grabber/BUILD.gn b/tools/android/audio_focus_grabber/BUILD.gn
index 08cfabb..11afd1c 100644
--- a/tools/android/audio_focus_grabber/BUILD.gn
+++ b/tools/android/audio_focus_grabber/BUILD.gn
@@ -12,6 +12,7 @@
   deps = [
     ":audio_focus_grabber_apk_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_core_core_java",
   ]
diff --git a/tools/android/kerberos/SpnegoAuthenticator/BUILD.gn b/tools/android/kerberos/SpnegoAuthenticator/BUILD.gn
index be7bead2..1f1338e2 100644
--- a/tools/android/kerberos/SpnegoAuthenticator/BUILD.gn
+++ b/tools/android/kerberos/SpnegoAuthenticator/BUILD.gn
@@ -14,6 +14,7 @@
   deps = [
     ":spnego_authenticator_apk_assets",
     "//base:base_java",
+    "//build/android:build_java",
     "//net/android:net_java",
   ]
 
diff --git a/tools/android/memconsumer/BUILD.gn b/tools/android/memconsumer/BUILD.gn
index f490d8a..7d47045 100644
--- a/tools/android/memconsumer/BUILD.gn
+++ b/tools/android/memconsumer/BUILD.gn
@@ -24,6 +24,7 @@
   deps = [
     ":memconsumer_apk_resources",
     "//base:base_java",
+    "//build/android:build_java",
   ]
 }
 
diff --git a/tools/binary_size/diagnose_bloat.py b/tools/binary_size/diagnose_bloat.py
index 650a794..006c1ba8 100755
--- a/tools/binary_size/diagnose_bloat.py
+++ b/tools/binary_size/diagnose_bloat.py
@@ -770,7 +770,8 @@
   if extra_rev:
     git_fatal(['cat-file', '-e', extra_rev], no_obj_message % extra_rev)
   git_fatal(['merge-base', '--is-ancestor', reference_rev, rev],
-            'reference-rev is newer than rev')
+            f'reference-rev ({reference_rev}) is not an ancestor of '
+            f'rev ({rev})')
 
 
 def _VerifyUserAccepts(message):
diff --git a/tools/cast3p/OWNERS b/tools/cast3p/OWNERS
index e0fc48a2..c923015 100644
--- a/tools/cast3p/OWNERS
+++ b/tools/cast3p/OWNERS
@@ -3,5 +3,5 @@
 riazantsevv@google.com
 rwkeane@google.com
 
-per-file cast_core.version=chromium-internal-autoroll@skia-public.iam.gserviceaccount.com
-per-file runtime.version=chromium-internal-autoroll@skia-public.iam.gserviceaccount.com
\ No newline at end of file
+per-file cast_core.version=chromium-internal-autoroll@skia-corp.google.com.iam.gserviceaccount.com
+per-file runtime.version=chromium-internal-autoroll@skia-corp.google.com.iam.gserviceaccount.com
\ No newline at end of file
diff --git a/tools/grit/grit/grd_reader.py b/tools/grit/grit/grd_reader.py
index 3ffa4dc9..4f81dc4 100755
--- a/tools/grit/grit/grd_reader.py
+++ b/tools/grit/grit/grd_reader.py
@@ -28,7 +28,7 @@
 
 class GrdContentHandler(xml.sax.handler.ContentHandler):
   def __init__(self, stop_after, debug, dir, defines, tags_to_ignore,
-               target_platform, source):
+               target_platform, source, skip_validation_checks):
     # Invariant of data:
     # 'root' is the root of the parse tree being created, or None if we haven't
     # parsed out any elements.
@@ -45,6 +45,7 @@
     self.ignore_depth = 0
     self.target_platform = target_platform
     self.source = source
+    self.skip_validation_checks = skip_validation_checks
 
   def startElement(self, name, attrs):
     if self.ignore_depth or name in self.tags_to_ignore:
@@ -74,6 +75,7 @@
       node.StartParsing(name, None)
       if self.defines:
         node.SetDefines(self.defines)
+      node.skip_validation_checks = self.skip_validation_checks
     self.stack.append(node)
 
     for attr, attrval in attrs.items():
@@ -146,9 +148,16 @@
     self.parent.ignorableWhitespace(whitespace)
 
 
-def Parse(filename_or_stream, dir=None, stop_after=None, first_ids_file=None,
-          debug=False, defines=None, tags_to_ignore=None, target_platform=None,
-          predetermined_ids_file=None):
+def Parse(filename_or_stream,
+          dir=None,
+          stop_after=None,
+          first_ids_file=None,
+          debug=False,
+          defines=None,
+          tags_to_ignore=None,
+          target_platform=None,
+          predetermined_ids_file=None,
+          skip_validation_checks=False):
   '''Parses a GRD file into a tree of nodes (from grit.node).
 
   If filename_or_stream is a stream, 'dir' should point to the directory
@@ -180,6 +189,9 @@
     predetermined_ids_file: File path to a file containing a pre-determined
         mapping from resource names to resource ids which will be used to assign
         resource ids to those resources.
+    skip_validation_checks: Whether to skip any validation after successfull
+        parsing, for example uniqueness of IDs, or that all variables encountered
+        in <if expr> statements are defined.
 
   Return:
     Subclass of grit.node.base.Node
@@ -195,9 +207,14 @@
   else:
     source = None
 
-  handler = GrdContentHandler(stop_after=stop_after, debug=debug, dir=dir,
-                              defines=defines, tags_to_ignore=tags_to_ignore,
-                              target_platform=target_platform, source=source)
+  handler = GrdContentHandler(stop_after=stop_after,
+                              debug=debug,
+                              dir=dir,
+                              defines=defines,
+                              tags_to_ignore=tags_to_ignore,
+                              target_platform=target_platform,
+                              source=source,
+                              skip_validation_checks=skip_validation_checks)
   try:
     xml.sax.parse(filename_or_stream, handler)
   except StopParsingException:
diff --git a/tools/grit/grit/grd_reader_unittest.py b/tools/grit/grit/grd_reader_unittest.py
index 3540c0e..c68fd28c 100755
--- a/tools/grit/grit/grd_reader_unittest.py
+++ b/tools/grit/grit/grd_reader_unittest.py
@@ -22,6 +22,7 @@
 from grit import util
 from grit.node import empty
 from grit.node import message
+from grit.exception import DuplicateKey
 
 
 class GrdReaderUnittest(unittest.TestCase):
@@ -341,6 +342,32 @@
       grd_reader.Parse(StringIO(grd_text), temp_dir.GetPath(),
                        target_platform='android')
 
+  def testSkipValidationChecks(self):
+    input = u'''<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+  <release seq="3">
+    <messages>
+      <message name="IDS_MESSAGE1" desc="description 1">
+        Message1
+      </message>
+      <message name="IDS_MESSAGE1" desc="description 1">
+        Another message with the same |name|
+      </message>
+    </messages>
+  </release>
+</grit>'''
+    pseudo_file = StringIO(input)
+
+    # Test when |skip_validation_checks| is set, no error is thrown.
+    grd_reader.Parse(pseudo_file, '.', skip_validation_checks=True)
+
+    # Test when |skip_validation_checks| is set, an error is thrown.
+    with self.assertRaises(DuplicateKey) as cm:
+      pseudo_file = StringIO(input)
+      grd_reader.Parse(pseudo_file, '.')
+    self.assertTrue(
+        str(cm.exception).startswith('A duplicate key attribute was found.'))
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/tools/grit/grit/node/misc.py b/tools/grit/grit/node/misc.py
index ba903652..18f3400 100644
--- a/tools/grit/grit/node/misc.py
+++ b/tools/grit/grit/node/misc.py
@@ -336,6 +336,10 @@
     self._predetermined_ids_file = None
     self._id_map = None  # Dict of textual_id -> numeric_id.
 
+    # Option to skip any post-parsing validation, useful when only interested
+    # in getting a reference to the parse tree.
+    self.skip_validation_checks = False
+
   def _IsValidChild(self, child):
     from grit.node import empty
     return isinstance(child, (ReleaseNode, empty.TranslationsNode,
@@ -372,6 +376,9 @@
       raise exception.Parsing('latest_public_release cannot have a greater '
                               'value than current_release')
 
+    if self.skip_validation_checks:
+      return
+
     self.ValidateUniqueIds()
 
     # Add the encoding check if it's not present (should ensure that it's always
diff --git a/tools/grit/grit/tool/update_resource_ids/reader.py b/tools/grit/grit/tool/update_resource_ids/reader.py
index 0a156d2..377f7b0 100644
--- a/tools/grit/grit/tool/update_resource_ids/reader.py
+++ b/tools/grit/grit/tool/update_resource_ids/reader.py
@@ -23,7 +23,9 @@
 def _CountResourceUsage(grd, seen_files):
   tag_name_to_count = {tag: set() for tag in TAGS_OF_INTEREST}
   # Pass '_chromium', but '_google_chrome' would produce the same result.
-  root = grd_reader.Parse(grd, defines={'_chromium': True})
+  root = grd_reader.Parse(grd,
+                          defines={'_chromium': True},
+                          skip_validation_checks=True)
   seen_files.add(grd)
   # Count all descendant tags, regardless of whether they're active.
   for node in root.Preorder():
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 5ada377..ce797c2 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -55,6 +55,7 @@
       'android-archive-dbg': 'android_without_codecs_debug_bot_reclient',
       'android-official': 'android_official_optimize_reclient',
       'fuchsia-official': 'fuchsia_official_optimize_goma',
+      'lacros64-archive-rel': 'chromeos_amd64-generic_lacros_rel',
       'linux-archive-rel': 'release_bot_reclient',
       'linux-archive-dbg': 'debug_bot_reclient',
       'linux-archive-tagged': 'official_optimize_reclient',
@@ -159,7 +160,7 @@
       'chromeos-amd64-generic-cfi-thin-lto-rel': 'chromeos_amd64-generic_cfi_thin_lto',
       'chromeos-amd64-generic-dbg': 'chromeos_amd64-generic_dbg_reclient',
       'chromeos-amd64-generic-dbg (reclient shadow)': 'chromeos_amd64-generic_dbg_reclient',
-      'chromeos-amd64-generic-lacros-dbg': 'chromeos_amd64-generic_lacros_dbg',
+      'chromeos-amd64-generic-lacros-dbg': 'chromeos_amd64-generic_lacros_dbg_reclient',
       'chromeos-amd64-generic-rel': 'chromeos_amd64-generic-vm_use_fake_dbus_clients_reclient',
       'chromeos-arm-generic-dbg': 'chromeos_arm-generic_dbg_reclient',
       'chromeos-arm-generic-dbg (reclient shadow)': 'chromeos_arm-generic_dbg_reclient',
@@ -172,11 +173,11 @@
       'lacros-arm-generic-rel': 'chromeos_arm-generic_lacros_rel',
       'linux-ash-chromium-generator-rel': 'chromeos_with_codecs_release_bot',
       'linux-chromeos-rel': 'chromeos_with_codecs_with_lacros_release_bot',
-      'linux-chromeos-dbg': 'chromeos_with_codecs_debug_bot',
+      'linux-chromeos-dbg': 'chromeos_with_codecs_debug_bot_reclient',
       'linux-lacros-builder-rel': 'lacros_on_linux_release_bot',
       'linux-lacros-dbg': 'lacros_on_linux_debug_bot',
       'linux-lacros-tester-rel': 'lacros_on_linux_release_bot',
-      'linux-cfm-rel': 'linux_cfm_release_bot',
+      'linux-cfm-rel': 'linux_cfm_release_bot_reclient',
     },
 
     'chromium.clang': {
@@ -375,12 +376,12 @@
       'lacros-amd64-generic-rel (goma cache silo)': 'chromeos_amd64-generic_lacros_rel',
       'lacros-amd64-generic-rel (reclient)': 'chromeos_amd64-generic-vm_lacros_rel_reclient',
       'linux-annotator-rel': 'release_bot_reclient',
-      'linux-chromeos-annotator-rel': 'chromeos_with_codecs_release_bot',
+      'linux-chromeos-annotator-rel': 'chromeos_with_codecs_release_bot_reclient',
       'linux-blink-animation-use-time-delta': 'debug_bot_enable_blink_animation_use_time_delta',
       'linux-blink-heap-concurrent-marking-tsan-rel': 'release_trybot_minimal_symbols_tsan',
       'linux-blink-heap-verification': 'release_bot_enable_blink_heap_verification_dcheck_always_on_reclient',
       'linux-blink-v8-sandbox-future-dbg': 'debug_bot_enable_v8_sandbox_future_reclient',
-      'linux-chromeos-code-coverage': 'chromeos_with_codecs_release_bot_coverage',
+      'linux-chromeos-code-coverage': 'chromeos_with_codecs_release_bot_coverage_reclient',
       'linux-chromeos-js-code-coverage': 'chromeos_with_codecs_release_bot_javascript_coverage',
       'linux-code-coverage': 'clang_code_coverage',
       'linux-example-builder': 'release_bot_reclient',
@@ -1954,8 +1955,8 @@
       'chromeos_amd64-generic-vm_reclient', 'lacros',
     ],
 
-    'chromeos_amd64-generic_lacros_dbg': [
-      'chromeos_amd64-generic-crostoolchain', 'lacros', 'debug', 'static',
+    'chromeos_amd64-generic_lacros_dbg_reclient': [
+      'chromeos_amd64-generic-crostoolchain_reclient', 'lacros', 'debug', 'static',
     ],
 
     'chromeos_amd64-generic_dbg': [
@@ -2102,6 +2103,10 @@
       'chromeos_with_codecs', 'debug_bot',
     ],
 
+    'chromeos_with_codecs_debug_bot_reclient': [
+      'chromeos_with_codecs', 'debug_bot_reclient',
+    ],
+
     'chromeos_with_codecs_release_bot': [
       'chromeos_with_codecs', 'release_bot',
     ],
@@ -2114,8 +2119,8 @@
       'chromeos_with_codecs', 'release_bot', 'also_build_lacros_chrome'
     ],
 
-    'chromeos_with_codecs_release_bot_coverage': [
-      'chromeos_with_codecs', 'release_bot', 'use_clang_coverage',
+    'chromeos_with_codecs_release_bot_coverage_reclient': [
+      'chromeos_with_codecs', 'release_bot_reclient', 'use_clang_coverage',
     ],
 
     'chromeos_with_codecs_release_bot_javascript_coverage': [
@@ -2899,8 +2904,8 @@
       'libfuzzer', 'asan', 'release_trybot', 'chrome_with_codecs', 'pdf_xfa', 'disable_nacl', 'mojo_fuzzer', 'skip_generate_fuzzer_owners', 'no_symbols',
     ],
 
-    'linux_cfm_release_bot': [
-      'cfm', 'release_bot', 'chromeos',
+    'linux_cfm_release_bot_reclient': [
+      'cfm', 'release_bot_reclient', 'chromeos',
     ],
 
     'linux_cfm_release_trybot': [
@@ -3590,6 +3595,10 @@
       'mixins': ['chromeos_device', 'amd64-generic-crostoolchain',]
     },
 
+    'chromeos_amd64-generic-crostoolchain_reclient': {
+      'mixins': ['chromeos_device_reclient', 'amd64-generic-crostoolchain',]
+    },
+
     'chromeos_arm-generic-crostoolchain': {
       'mixins': ['chromeos_device', 'arm-generic-crostoolchain',]
     },
diff --git a/tools/mb/mb_config_expectations/chromium.chromiumos.json b/tools/mb/mb_config_expectations/chromium.chromiumos.json
index 262cf6d..a574628 100644
--- a/tools/mb/mb_config_expectations/chromium.chromiumos.json
+++ b/tools/mb/mb_config_expectations/chromium.chromiumos.json
@@ -89,7 +89,8 @@
       "is_debug": true,
       "ozone_platform_headless": true,
       "target_os": "chromeos",
-      "use_goma": true
+      "use_rbe": true,
+      "use_remoteexec": true
     }
   },
   "chromeos-amd64-generic-rel": {
@@ -218,7 +219,8 @@
       "is_component_build": false,
       "is_debug": false,
       "target_os": "chromeos",
-      "use_goma": true
+      "use_rbe": true,
+      "use_remoteexec": true
     }
   },
   "linux-chromeos-dbg": {
@@ -229,7 +231,8 @@
       "proprietary_codecs": true,
       "symbol_level": 1,
       "target_os": "chromeos",
-      "use_goma": true
+      "use_rbe": true,
+      "use_remoteexec": true
     }
   },
   "linux-chromeos-rel": {
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json
index 986b772..12d4567 100644
--- a/tools/mb/mb_config_expectations/chromium.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -1062,7 +1062,8 @@
       "is_debug": false,
       "proprietary_codecs": true,
       "target_os": "chromeos",
-      "use_goma": true
+      "use_rbe": true,
+      "use_remoteexec": true
     }
   },
   "linux-chromeos-code-coverage": {
@@ -1074,7 +1075,8 @@
       "proprietary_codecs": true,
       "target_os": "chromeos",
       "use_clang_coverage": true,
-      "use_goma": true
+      "use_rbe": true,
+      "use_remoteexec": true
     }
   },
   "linux-chromeos-js-code-coverage": {
diff --git a/tools/mb/mb_config_expectations/chromium.json b/tools/mb/mb_config_expectations/chromium.json
index ea18abe8..e43d0ed 100644
--- a/tools/mb/mb_config_expectations/chromium.json
+++ b/tools/mb/mb_config_expectations/chromium.json
@@ -36,6 +36,18 @@
       "use_goma": true
     }
   },
+  "lacros64-archive-rel": {
+    "args_file": "//build/args/chromeos/amd64-generic-crostoolchain.gni",
+    "gn_args": {
+      "chromeos_is_browser_only": true,
+      "dcheck_always_on": false,
+      "is_chromeos_device": true,
+      "is_debug": false,
+      "ozone_platform_headless": true,
+      "target_os": "chromeos",
+      "use_goma": true
+    }
+  },
   "linux-archive-dbg": {
     "gn_args": {
       "is_component_build": true,
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index baac6d9..c82ac9f 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -18629,6 +18629,16 @@
   </description>
 </action>
 
+<action name="MobileRecentTabManagerRecentTabsCleared">
+  <owner>ckitagawa@chromium.org</owner>
+  <owner>fredmello@chromium.org</owner>
+  <description>
+    Recorded on Android when a user clears all entries using the context menu
+    from Recent Tabs &gt; Recently Closed. This corresponds to clearing the
+    native TabRestoreService.
+  </description>
+</action>
+
 <action name="MobileRecentTabManagerShowFullHistory">
   <owner>gambard@google.com</owner>
   <owner>sczs@chromium.org</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index f17093e..ff7aa055 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -29403,6 +29403,23 @@
   <int value="981" label="UrlParamFilterEnabled"/>
 </enum>
 
+<enum name="EnterprisePoliciesSources">
+  <int value="0" label="Cloud only">
+    All policies are set from cloud. This also includes cloud_ash policy source
+  </int>
+  <int value="1" label="Cloud only except enrollment">
+    All policies are set from cloud except CBCM enrollment token and option.
+  </int>
+  <int value="2" label="Platform only">
+    All policies are set from platform management tool. This also includes AD
+    policeis on CrOS.
+  </int>
+  <int value="3" label="Hybrid">Policies are set with multiple tools.</int>
+  <int value="4" label="EnrollmentOnly">
+    There is no policy except CBCM enrollment token and option.
+  </int>
+</enum>
+
 <enum name="EnterprisePolicyDeviceIdValidity">
   <summary>
     Defined as PolicyDeviceIdValidity in
@@ -44815,6 +44832,12 @@
   <int value="2147480259" label="Sqlite.Vfs_Fetch"/>
 </enum>
 
+<enum name="HistoricalSaverCloseType">
+  <int value="0" label="Tab"/>
+  <int value="1" label="Group"/>
+  <int value="2" label="Bulk"/>
+</enum>
+
 <enum name="HistoryClustersFinalState">
   <summary>
     The final state, or outcome, of an interaction on the HistoryClusters, or
@@ -52704,6 +52727,7 @@
   <int value="-1863962664" label="LockScreenNotifications:enabled"/>
   <int value="-1863020461" label="PasswordChangeInSettings:enabled"/>
   <int value="-1861814223" label="MidiManagerDynamicInstantiation:enabled"/>
+  <int value="-1861278695" label="BulkTabRestore:enabled"/>
   <int value="-1860481724" label="ChromeHomeExpandButton:enabled"/>
   <int value="-1860477300" label="DefaultStyleSheetsEarlyInit:disabled"/>
   <int value="-1859437916"
@@ -57689,6 +57713,7 @@
   <int value="1498398756" label="TemporaryHoldingSpace:disabled"/>
   <int value="1499163193" label="PostScriptPrinting:disabled"/>
   <int value="1500390299" label="NtpCustomizationMenuV2:disabled"/>
+  <int value="1502417134" label="BulkTabRestore:disabled"/>
   <int value="1505194447" label="disable-transition-compositing"/>
   <int value="1506372577" label="NearbySharingSelfShare:disabled"/>
   <int value="1507233295" label="FilesTrash:disabled"/>
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml
index c9985c35c..c43c5e5 100644
--- a/tools/metrics/histograms/metadata/chromeos/histograms.xml
+++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -1027,6 +1027,9 @@
 
 <histogram name="ChromeOS.KeyPermissionsManager.MigrationTime" units="ms"
     expires_after="2022-02-06">
+  <obsolete>
+    Removed in M103
+  </obsolete>
   <owner>omorsi@google.com</owner>
   <owner>pmarko@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml
index 7f746c2..6b46d31a 100644
--- a/tools/metrics/histograms/metadata/enterprise/histograms.xml
+++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -1791,6 +1791,19 @@
   </summary>
 </histogram>
 
+<histogram name="Enterprise.Policies.Sources" enum="EnterprisePoliciesSources"
+    expires_after="2023-04-01">
+  <owner>zmin@chromium.org</owner>
+  <owner>igorruvinov@chromium.org</owner>
+  <summary>
+    Record summary of sources of all policies. It's recorded ever 24 hours and
+    at startup.
+
+    This does not include user cloud policy and some speicial policy sources
+    like enterprise_default.
+  </summary>
+</histogram>
+
 <histogram name="Enterprise.Policies.{PolicyLevel}" enum="EnterprisePolicies"
     expires_after="2023-03-01">
   <owner>zmin@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml
index cd792a2..129b916 100644
--- a/tools/metrics/histograms/metadata/history/histograms.xml
+++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -957,6 +957,25 @@
   </token>
 </histogram>
 
+<histogram name="History.Clusters.WebUISessionDuration" units="ms"
+    expires_after="2022-11-30">
+  <owner>tommycli@chromium.org</owner>
+  <owner>chrome-journeys@google.com</owner>
+  <summary>
+    Records the amount of time the Journeys WebUI is open.
+
+    This timer is started when the Journeys WebUI is loaded. The Journeys WebUI
+    is loaded when either the user directly goes to the Journeys WebUI, or when
+    the user switches to the Journeys tab from a different tab.
+
+    The timer is stopped and the elapsed time recorded when either the whole
+    WebUI is closed, or if the user disables the Journeys preference, or if the
+    user switches tabs off the Journeys tab onto a different one.
+
+    Elapsed times longer than one hour are recorded as one hour.
+  </summary>
+</histogram>
+
 <histogram name="History.DatabaseAdvancedMetricsTime" units="ms"
     expires_after="M77">
   <owner>shess@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index 337e440..2334ceb 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -8872,54 +8872,6 @@
   </summary>
 </histogram>
 
-<histogram
-    name="PerformanceManager.FrameSiteInstanceProcessRelationship.ByProcess2"
-    enum="FrameSiteInstanceProcessRelationship" expires_after="2020-12-31">
-  <owner>chrisha@chromium.org</owner>
-  <owner>catan-team@chromium.org</owner>
-  <summary>
-    Tracks the types of frames that are being hosted by a process over its
-    entire lifetime. An entry in the
-    &quot;AllFramesHaveDistinctSiteInstances&quot; means that the process only
-    ever hosted frames with distinct site instances over its entire lifetime.
-    Recorded on state changes and every 5 minutes.
-  </summary>
-</histogram>
-
-<histogram
-    name="PerformanceManager.FrameSiteInstanceProcessRelationship.ByTime2"
-    enum="FrameSiteInstanceProcessRelationship" expires_after="2020-12-31">
-  <owner>chrisha@chromium.org</owner>
-  <owner>catan-team@chromium.org</owner>
-  <summary>
-    Tracks the types of frames that are being hosted by a process, aggregated
-    over time. Each entry in each bucket corresponds to a process being in that
-    state for one second. Recorded on state changes and every 5 minutes.
-  </summary>
-</histogram>
-
-<histogram name="PerformanceManager.FramesPerRendererByTime" units="units"
-    expires_after="2021-03-07">
-  <owner>chrisha@chromium.org</owner>
-  <owner>catan-team@chromium.org</owner>
-  <summary>
-    Tracks the number of frames hosted per renderer by time. An entry in bucket
-    N corresponds to N frames being hosted by a renderer process for 1 second.
-    Recorded on state changes and every 5 minutes.
-  </summary>
-</histogram>
-
-<histogram name="PerformanceManager.SiteInstancesPerRendererByTime"
-    units="units" expires_after="2020-12-31">
-  <owner>chrisha@chromium.org</owner>
-  <owner>catan-team@chromium.org</owner>
-  <summary>
-    Tracks the number of site instances hosted per renderer by time. An entry in
-    bucket N corresponds to N site instances being hosted by a renderer process
-    for 1 second. Recorded on state changes and every 5 minutes.
-  </summary>
-</histogram>
-
 <histogram name="PerformanceManager.WorkerClientFound" enum="BooleanFound"
     expires_after="2020-11-30">
   <owner>pmonette@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/platform/histograms.xml b/tools/metrics/histograms/metadata/platform/histograms.xml
index 070b8af..9973e2c 100644
--- a/tools/metrics/histograms/metadata/platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/platform/histograms.xml
@@ -724,7 +724,7 @@
 </histogram>
 
 <histogram name="Platform.MiniDiag.Launch" units="launches"
-    expires_after="2022-05-18">
+    expires_after="2022-11-18">
   <owner>roccochen@chromium.org</owner>
   <owner>chromeos-minidiag-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/prefetch/histograms.xml b/tools/metrics/histograms/metadata/prefetch/histograms.xml
index 25372e97..094671a 100644
--- a/tools/metrics/histograms/metadata/prefetch/histograms.xml
+++ b/tools/metrics/histograms/metadata/prefetch/histograms.xml
@@ -52,7 +52,7 @@
 
 <histogram
     name="PrefetchProxy.CanaryChecker.CacheEntryAge.{PrefetchProxyCanaryCheckerClient}"
-    units="hours" expires_after="M104">
+    units="hours" expires_after="2023-04-25">
   <owner>spelchat@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
@@ -64,7 +64,7 @@
 
 <histogram
     name="PrefetchProxy.CanaryChecker.CacheLookupResult.{PrefetchProxyCanaryCheckerClient}"
-    enum="CanaryCheckLookupResult" expires_after="M104">
+    enum="CanaryCheckLookupResult" expires_after="2023-04-25">
   <owner>spelchat@chromium.org</owner>
   <owner>chrome-brapp-loading@google.com</owner>
   <summary>
@@ -79,7 +79,7 @@
 
 <histogram
     name="PrefetchProxy.CanaryChecker.FinalState.{PrefetchProxyCanaryCheckerClient}"
-    enum="BooleanSuccess" expires_after="M104">
+    enum="BooleanSuccess" expires_after="2023-04-25">
   <owner>spelchat@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
@@ -93,7 +93,7 @@
 
 <histogram
     name="PrefetchProxy.CanaryChecker.GenerateCacheKey.{PrefetchProxyCanaryCheckerClient}"
-    units="ms" expires_after="M104">
+    units="ms" expires_after="2023-04-25">
   <owner>spelchat@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
@@ -107,7 +107,7 @@
 
 <histogram
     name="PrefetchProxy.CanaryChecker.NetError.{PrefetchProxyCanaryCheckerClient}"
-    enum="NetErrorCodes" expires_after="M104">
+    enum="NetErrorCodes" expires_after="2023-04-25">
   <owner>spelchat@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
@@ -121,7 +121,7 @@
 
 <histogram
     name="PrefetchProxy.CanaryChecker.NumAttemptsBeforeSuccess.{PrefetchProxyCanaryCheckerClient}"
-    units="count" expires_after="M104">
+    units="count" expires_after="2023-04-25">
   <owner>spelchat@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
@@ -138,7 +138,7 @@
 
 <histogram
     name="PrefetchProxy.CanaryChecker.TimeUntilFailure.{PrefetchProxyCanaryCheckerClient}"
-    units="ms" expires_after="M104">
+    units="ms" expires_after="2023-04-25">
   <owner>spelchat@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
@@ -151,7 +151,7 @@
 
 <histogram
     name="PrefetchProxy.CanaryChecker.TimeUntilSuccess.{PrefetchProxyCanaryCheckerClient}"
-    units="ms" expires_after="M104">
+    units="ms" expires_after="2023-04-25">
   <owner>spelchat@chromium.org</owner>
   <owner>chrome-brapp-loading@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index 782ee31..dc3419bf 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -28,6 +28,12 @@
   <variant name=".PluggedIn"/>
 </variants>
 
+<variants name="RecentlyClosedType">
+  <variant name="Bulk" summary="RecentlyClosedBulkEvent"/>
+  <variant name="Group" summary="RecentlyClosedGroup"/>
+  <variant name="Tab" summary="RecentlyClosedTab"/>
+</variants>
+
 <variants name="TabActiveState">
   <variant name="Active" summary="active"/>
   <variant name="Inactive" summary="inactive"/>
@@ -1933,6 +1939,56 @@
   </summary>
 </histogram>
 
+<histogram
+    name="Tabs.RecentlyClosed.EntriesRestoredInPage.{RecentlyClosedType}"
+    units="entries restored" expires_after="2022-10-01">
+  <owner>ckitagawa@chromium.org</owner>
+  <owner>fredmello@chromium.org</owner>
+  <summary>
+    The number of distinct entries from TabRestoreService of
+    {RecentlyClosedType} type that were restored in one Recent Tabs page session
+    on Android. This is recorded when destroying the Recent Tabs page if any
+    entires of {RecentlyClosedType} type were shown.
+  </summary>
+</histogram>
+
+<histogram name="Tabs.RecentlyClosed.EntriesShownInPage.{RecentlyClosedType}"
+    units="entries shown" expires_after="2022-10-01">
+  <owner>ckitagawa@chromium.org</owner>
+  <owner>fredmello@chromium.org</owner>
+  <summary>
+    The number of distinct entries from TabRestoreService of
+    {RecentlyClosedType} type shown in one Recent Tabs page session on Android.
+    This is recorded when destroying the Recent Tabs page.
+  </summary>
+</histogram>
+
+<histogram name="Tabs.RecentlyClosed.HistoricalSaverCloseType"
+    enum="HistoricalSaverCloseType" expires_after="2022-10-01">
+  <owner>ckitagawa@chromium.org</owner>
+  <owner>fredmello@chromium.org</owner>
+  <summary>
+    Recorded once for each tab closure event processed by HistoricalTabSaverImpl
+    on Android. Enum categories correspond to the the type of closure that was
+    saved to the native TabRestoreService. Tab for single tab, Group for a
+    single tab group and Bulk for a combination of tabs and groups or more than
+    one of either.
+  </summary>
+</histogram>
+
+<histogram
+    name="Tabs.RecentlyClosed.PercentOfEntriesRestoredInPage.{RecentlyClosedType}"
+    units="percentage restored" expires_after="2022-10-01">
+  <owner>ckitagawa@chromium.org</owner>
+  <owner>fredmello@chromium.org</owner>
+  <summary>
+    The percentage of entries from TabRestoreService of {RecentlyClosedType}
+    type that were restored relative to the number shown in one Recent Tabs page
+    session on Android. This is recorded when destroying the Recent Tabs page if
+    any entires of {RecentlyClosedType} type were shown.
+  </summary>
+</histogram>
+
 <histogram name="Tabs.SadTab.Feedback.Event" enum="SadTabEvent"
     expires_after="2022-08-28">
   <owner>sonnyrao@chromium.org</owner>
diff --git a/tools/translation/helper/grd_helper.py b/tools/translation/helper/grd_helper.py
index 651d992..b68bcbd 100644
--- a/tools/translation/helper/grd_helper.py
+++ b/tools/translation/helper/grd_helper.py
@@ -37,14 +37,14 @@
   """Load the grd file and return a dict of message ids to messages.
 
   Ignores non-translateable messages."""
-  doc = grit.grd_reader.Parse(
-      grd_path_or_string,
-      dir_path,
-      stop_after=None,
-      first_ids_file=None,
-      debug=False,
-      defines={'_chromium': 1},
-      tags_to_ignore=set(TAGS_TO_IGNORE))
+  doc = grit.grd_reader.Parse(grd_path_or_string,
+                              dir_path,
+                              stop_after=None,
+                              first_ids_file=None,
+                              debug=False,
+                              defines={'_chromium': 1},
+                              tags_to_ignore=set(TAGS_TO_IGNORE),
+                              skip_validation_checks=True)
   return {
       msg.attrs['name']: msg
       for msg in doc.GetChildrenOfType(grit.node.message.MessageNode)
diff --git a/tools/translation/testdata/test.grd b/tools/translation/testdata/test.grd
index 02023a7e..e9f6001 100644
--- a/tools/translation/testdata/test.grd
+++ b/tools/translation/testdata/test.grd
@@ -15,6 +15,12 @@
       <message name="IDS_TEST_STRING_NON_TRANSLATEABLE" translateable="false">
         This is a non translateable string
       </message>
+      <!-- Check that undefined Grit variables don't cause parsing to fail. -->
+      <if expr="foo_undefined">
+        <message name="IDS_TEST_STRING3">
+          This is string guarded by an if-expr.
+        </message>
+      </if>
       <part file="part.grdp" />
     </messages>
   </release>
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index 0971948..bbaf282 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -363,6 +363,7 @@
     ":ui_java_resources",
     ":ui_utils_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/url_formatter/android:url_formatter_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
@@ -440,6 +441,7 @@
     ":ui_java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//components/browser_ui/modaldialog/android:java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
     "//third_party/androidx:androidx_appcompat_appcompat_resources_java",
@@ -510,6 +512,7 @@
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//base/test:test_support_java",
+    "//build/android:build_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_appcompat_appcompat_resources_java",
     "//third_party/androidx:androidx_asynclayoutinflater_asynclayoutinflater_java",
@@ -570,6 +573,7 @@
   deps = [
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
   ]
 }
 
@@ -587,6 +591,7 @@
     ":ui_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/hamcrest:hamcrest_library_java",
diff --git a/ui/views/examples/BUILD.gn b/ui/views/examples/BUILD.gn
index 99b6ad5..2728e5d9 100644
--- a/ui/views/examples/BUILD.gn
+++ b/ui/views/examples/BUILD.gn
@@ -35,6 +35,8 @@
     "combobox_example.h",
     "create_examples.cc",
     "create_examples.h",
+    "designer_example.cc",
+    "designer_example.h",
     "dialog_example.cc",
     "dialog_example.h",
     "example_base.cc",
diff --git a/ui/views/examples/create_examples.cc b/ui/views/examples/create_examples.cc
index b299d16..2998364 100644
--- a/ui/views/examples/create_examples.cc
+++ b/ui/views/examples/create_examples.cc
@@ -19,6 +19,7 @@
 #include "ui/views/examples/colored_dialog_example.h"
 #include "ui/views/examples/colors_example.h"
 #include "ui/views/examples/combobox_example.h"
+#include "ui/views/examples/designer_example.h"
 #include "ui/views/examples/dialog_example.h"
 #include "ui/views/examples/fade_animation.h"
 #include "ui/views/examples/flex_layout_example.h"
@@ -70,6 +71,7 @@
   examples.push_back(std::make_unique<ColoredDialogExample>());
   examples.push_back(std::make_unique<ColorsExample>());
   examples.push_back(std::make_unique<ComboboxExample>());
+  examples.push_back(std::make_unique<DesignerExample>());
   examples.push_back(std::make_unique<DialogExample>());
   examples.push_back(std::make_unique<FadeAnimationExample>());
   examples.push_back(std::make_unique<FlexLayoutExample>());
diff --git a/ui/views/examples/designer_example.cc b/ui/views/examples/designer_example.cc
new file mode 100644
index 0000000..b897bd8
--- /dev/null
+++ b/ui/views/examples/designer_example.cc
@@ -0,0 +1,649 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/examples/designer_example.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/ranges/ranges.h"
+#include "base/strings/utf_string_conversions.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/metadata/metadata_types.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/color/color_id.h"
+#include "ui/events/event.h"
+#include "ui/events/event_targeter.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/views/background.h"
+#include "ui/views/controls/button/checkbox.h"
+#include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/button/md_text_button.h"
+#include "ui/views/controls/button/radio_button.h"
+#include "ui/views/controls/button/toggle_button.h"
+#include "ui/views/controls/combobox/combobox.h"
+#include "ui/views/controls/scroll_view.h"
+#include "ui/views/controls/table/table_view.h"
+#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/examples/examples_color_id.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/box_layout_view.h"
+#include "ui/views/metadata/view_factory.h"
+#include "ui/views/native_cursor.h"
+#include "ui/views/vector_icons.h"
+#include "ui/views/view.h"
+#include "ui/views/view_targeter.h"
+
+namespace views::examples {
+
+class DesignerSurface : public View {
+ public:
+  METADATA_HEADER(DesignerSurface);
+  explicit DesignerSurface(int grid_size = 8);
+  DesignerSurface(const DesignerSurface&) = delete;
+  DesignerSurface& operator=(const DesignerSurface&) = delete;
+  ~DesignerSurface() override = default;
+
+  int GetGridSize() const { return grid_size_; }
+  void SetGridSize(int grid_size);
+
+  // View overrides.
+  void OnPaint(gfx::Canvas* canvas) override;
+  void OnThemeChanged() override;
+
+ private:
+  void RebuildGridImage();
+
+  gfx::ImageSkia grid_image_;
+  int grid_size_ = 8;
+};
+
+DesignerSurface::DesignerSurface(int grid_size) : grid_size_(grid_size) {}
+
+void DesignerSurface::SetGridSize(int grid_size) {
+  if (grid_size_ != grid_size) {
+    grid_size_ = grid_size;
+    if (GetWidget())
+      RebuildGridImage();
+  }
+}
+
+void DesignerSurface::OnPaint(gfx::Canvas* canvas) {
+  views::View::OnPaint(canvas);
+  canvas->TileImageInt(grid_image_, 0, 0, size().width(), size().height());
+}
+
+void DesignerSurface::OnThemeChanged() {
+  View::OnThemeChanged();
+  RebuildGridImage();
+}
+
+void DesignerSurface::RebuildGridImage() {
+  const SkColor grid_color =
+      GetColorProvider()->GetColor(ExamplesColorIds::kColorDesignerGrid);
+  gfx::Size grid_size = grid_size_ <= 8
+                            ? gfx::Size(grid_size_ * 8, grid_size_ * 8)
+                            : gfx::Size(grid_size_, grid_size_);
+  auto grid_canvas = std::make_unique<gfx::Canvas>(grid_size, 1.0, false);
+  for (int i = 0; i < grid_size.width(); i += grid_size_) {
+    for (int j = 0; j < grid_size.height(); j += grid_size_) {
+      grid_canvas->FillRect(gfx::Rect(i, j, 1, 1), grid_color);
+    }
+  }
+  grid_image_ = gfx::ImageSkia::CreateFrom1xBitmap(grid_canvas->GetBitmap());
+}
+
+BEGIN_METADATA(DesignerSurface, View)
+ADD_PROPERTY_METADATA(int, GridSize)
+END_METADATA
+
+BEGIN_VIEW_BUILDER(/* no export */, DesignerSurface, View)
+VIEW_BUILDER_PROPERTY(int, GridSize)
+END_VIEW_BUILDER
+
+}  // namespace views::examples
+
+DEFINE_VIEW_BUILDER(/* no export */, views::examples::DesignerSurface)
+
+namespace views::examples {
+
+namespace {
+
+ui::TableColumn MakeColumn(int id, std::u16string title, bool sortable) {
+  ui::TableColumn column;
+  column.id = id;
+  column.title = title;
+  column.alignment = ui::TableColumn::LEFT;
+  column.width = -1;
+  column.percent = 0.5f;
+  column.sortable = sortable;
+  return column;
+}
+
+int SnapToInterval(int value, int interval) {
+  return value - (value % interval);
+}
+
+template <typename C>
+class ClassRegistration : public BaseClassRegistration {
+ public:
+  ClassRegistration() = default;
+  ~ClassRegistration() override = default;
+  std::unique_ptr<View> CreateView() override { return std::make_unique<C>(); }
+  std::u16string GetViewClassName() override {
+    return base::ASCIIToUTF16(C::MetaData()->type_name());
+  }
+};
+
+template <>
+class ClassRegistration<Combobox> : public BaseClassRegistration,
+                                    public ui::ComboboxModel {
+ public:
+  ClassRegistration() = default;
+  ~ClassRegistration() override = default;
+  std::unique_ptr<View> CreateView() override {
+    return std::make_unique<Combobox>(this);
+  }
+  std::u16string GetViewClassName() override {
+    return base::ASCIIToUTF16(Combobox::MetaData()->type_name());
+  }
+
+  // ui::ComboboxModel
+  int GetItemCount() const override { return 1; }
+  std::u16string GetItemAt(int index) const override { return u"<empty>"; }
+  int GetDefaultIndex() const override { return 0; }
+};
+
+template <>
+class ClassRegistration<MdTextButton> : public BaseClassRegistration {
+ public:
+  ClassRegistration() = default;
+  ~ClassRegistration() override = default;
+  std::unique_ptr<View> CreateView() override {
+    return Builder<MdTextButton>().SetText(u"Button").Build();
+  }
+  std::u16string GetViewClassName() override {
+    return base::ASCIIToUTF16(MdTextButton::MetaData()->type_name());
+  }
+};
+
+template <>
+class ClassRegistration<Textfield> : public BaseClassRegistration {
+ public:
+  ClassRegistration() = default;
+  ~ClassRegistration() override = default;
+  std::unique_ptr<View> CreateView() override {
+    const std::u16string text = u"<text field>";
+    return Builder<Textfield>()
+        .SetText(text)
+        .SetDefaultWidthInChars(text.size())
+        .Build();
+  }
+  std::u16string GetViewClassName() override {
+    return base::ASCIIToUTF16(Textfield::MetaData()->type_name());
+  }
+};
+
+template <>
+class ClassRegistration<Checkbox> : public BaseClassRegistration {
+ public:
+  ClassRegistration() = default;
+  ~ClassRegistration() override = default;
+  std::unique_ptr<View> CreateView() override {
+    return std::make_unique<Checkbox>(u"<Checkbox>");
+  }
+  std::u16string GetViewClassName() override {
+    return base::ASCIIToUTF16(Checkbox::MetaData()->type_name());
+  }
+};
+
+template <>
+class ClassRegistration<RadioButton> : public BaseClassRegistration {
+ public:
+  ClassRegistration() = default;
+  ~ClassRegistration() override = default;
+  std::unique_ptr<View> CreateView() override {
+    return std::make_unique<RadioButton>(u"<RadioButton>", 0);
+  }
+  std::u16string GetViewClassName() override {
+    return base::ASCIIToUTF16(RadioButton::MetaData()->type_name());
+  }
+};
+
+template <>
+class ClassRegistration<ToggleButton> : public BaseClassRegistration {
+ public:
+  ClassRegistration() = default;
+  ~ClassRegistration() override = default;
+  std::unique_ptr<View> CreateView() override {
+    return std::make_unique<ToggleButton>();
+  }
+  std::u16string GetViewClassName() override {
+    return base::ASCIIToUTF16(ToggleButton::MetaData()->type_name());
+  }
+};
+
+template <>
+class ClassRegistration<ImageButton> : public BaseClassRegistration {
+ public:
+  ClassRegistration() = default;
+  ~ClassRegistration() override = default;
+  std::unique_ptr<View> CreateView() override {
+    return Builder<ImageButton>()
+        .SetImage(Button::ButtonState::STATE_NORMAL,
+                  gfx::CreateVectorIcon(kPinIcon, ui::kColorIcon))
+        .Build();
+  }
+  std::u16string GetViewClassName() override {
+    return base::ASCIIToUTF16(ImageButton::MetaData()->type_name());
+  }
+};
+
+std::vector<std::unique_ptr<BaseClassRegistration>> GetClassRegistrations() {
+  std::vector<std::unique_ptr<BaseClassRegistration>> registrations;
+  registrations.push_back(std::make_unique<ClassRegistration<Checkbox>>());
+  registrations.push_back(std::make_unique<ClassRegistration<Combobox>>());
+  registrations.push_back(std::make_unique<ClassRegistration<MdTextButton>>());
+  registrations.push_back(std::make_unique<ClassRegistration<RadioButton>>());
+  registrations.push_back(std::make_unique<ClassRegistration<Textfield>>());
+  registrations.push_back(std::make_unique<ClassRegistration<ToggleButton>>());
+  registrations.push_back(std::make_unique<ClassRegistration<ImageButton>>());
+  return registrations;
+}
+
+bool IsViewParent(View* parent, View* view) {
+  while (view) {
+    if (view == parent)
+      return true;
+    view = view->parent();
+  }
+  return false;
+}
+
+View* GetDesignerChild(View* child_view, View* designer) {
+  while (child_view && child_view != designer &&
+         child_view->parent() != designer) {
+    child_view = child_view->parent();
+  }
+  return child_view;
+}
+
+}  // namespace
+
+BaseClassRegistration::~BaseClassRegistration() = default;
+
+DesignerExample::GrabHandle::GrabHandle(GrabHandles* grab_handles,
+                                        GrabHandlePosition position)
+    : position_(position), grab_handles_(grab_handles) {}
+
+DesignerExample::GrabHandle::~GrabHandle() = default;
+
+void DesignerExample::GrabHandle::SetAttachedView(View* view) {
+  bool was_visible = GetVisible() && attached_view_ != view;
+  attached_view_ = view;
+  SetVisible(!!attached_view_);
+  UpdatePosition(!was_visible);
+}
+
+void DesignerExample::GrabHandle::UpdatePosition(bool reorder) {
+  if (GetVisible() && attached_view_) {
+    PositionOnView();
+    if (reorder)
+      parent()->ReorderChildView(this, -1);
+  }
+}
+
+gfx::NativeCursor DesignerExample::GrabHandle::GetCursor(
+    const ui::MouseEvent& event) {
+  switch (position_) {
+    case GrabHandlePosition::kTop:
+    case GrabHandlePosition::kBottom:
+      return views::GetNativeNorthSouthResizeCursor();
+    case GrabHandlePosition::kLeft:
+    case GrabHandlePosition::kRight:
+      return views::GetNativeEastWestResizeCursor();
+    case GrabHandlePosition::kTopLeft:
+    case GrabHandlePosition::kBottomRight:
+      return views::GetNativeNorthWestSouthEastResizeCursor();
+    case GrabHandlePosition::kTopRight:
+    case GrabHandlePosition::kBottomLeft:
+      return views::GetNativeNorthEastSouthWestResizeCursor();
+  }
+}
+
+gfx::Size DesignerExample::GrabHandle::CalculatePreferredSize() const {
+  return gfx::Size(kGrabHandleSize, kGrabHandleSize);
+}
+
+void DesignerExample::GrabHandle::OnPaint(gfx::Canvas* canvas) {
+  SkPath path;
+  gfx::Point center = GetLocalBounds().CenterPoint();
+  path.addCircle(center.x(), center.y(), width() / 2);
+  cc::PaintFlags flags;
+  flags.setColor(
+      GetColorProvider()->GetColor(ExamplesColorIds::kColorDesignerGrabHandle));
+  flags.setAntiAlias(true);
+  canvas->DrawPath(path, flags);
+}
+
+bool DesignerExample::GrabHandle::OnMousePressed(const ui::MouseEvent& event) {
+  mouse_drag_pos_ = event.location();
+  return true;
+}
+
+bool DesignerExample::GrabHandle::OnMouseDragged(const ui::MouseEvent& event) {
+  gfx::Point new_location = event.location();
+  if (position_ == GrabHandlePosition::kTop ||
+      position_ == GrabHandlePosition::kBottom) {
+    new_location.set_x(mouse_drag_pos_.x());
+  }
+  if (position_ == GrabHandlePosition::kLeft ||
+      position_ == GrabHandlePosition::kRight) {
+    new_location.set_y(mouse_drag_pos_.y());
+  }
+  SetPosition(origin() + (new_location - mouse_drag_pos_));
+  UpdateViewSize();
+  grab_handles_->SetAttachedView(attached_view_);
+  return true;
+}
+
+void DesignerExample::GrabHandle::PositionOnView() {
+  DCHECK(attached_view_);
+  gfx::Rect view_bounds = attached_view_->bounds();
+  gfx::Point edge_position;
+  if (IsTop(position_)) {
+    edge_position.set_y(view_bounds.y());
+    if (position_ == GrabHandlePosition::kTop)
+      edge_position.set_x(view_bounds.top_center().x());
+  } else if (IsBottom(position_)) {
+    edge_position.set_y(view_bounds.bottom());
+    if (position_ == GrabHandlePosition::kBottom)
+      edge_position.set_x(view_bounds.bottom_center().x());
+  }
+  if (IsLeft(position_)) {
+    edge_position.set_x(view_bounds.x());
+    if (position_ == GrabHandlePosition::kLeft)
+      edge_position.set_y(view_bounds.left_center().y());
+  } else if (IsRight(position_)) {
+    edge_position.set_x(view_bounds.right());
+    if (position_ == GrabHandlePosition::kRight)
+      edge_position.set_y(view_bounds.right_center().y());
+  }
+  SetPosition(edge_position - (bounds().CenterPoint() - origin()));
+}
+
+void DesignerExample::GrabHandle::UpdateViewSize() {
+  DCHECK(attached_view_);
+  gfx::Rect view_bounds = attached_view_->bounds();
+  gfx::Point view_center = bounds().CenterPoint();
+  if (IsTop(position_)) {
+    view_bounds.set_height(view_bounds.height() -
+                           (view_center.y() - view_bounds.y()));
+    view_bounds.set_y(view_center.y());
+  }
+  if (IsBottom(position_))
+    view_bounds.set_height(view_center.y() - view_bounds.y());
+  if (IsLeft(position_)) {
+    view_bounds.set_width(view_bounds.width() -
+                          (view_center.x() - view_bounds.x()));
+    view_bounds.set_x(view_center.x());
+  }
+  if (IsRight(position_))
+    view_bounds.set_width(view_center.x() - view_bounds.x());
+  attached_view_->SetBoundsRect(view_bounds);
+}
+
+// static
+bool DesignerExample::GrabHandle::IsTop(GrabHandlePosition position) {
+  return (position & GrabHandlePosition::kTop);
+}
+
+// static
+bool DesignerExample::GrabHandle::IsBottom(GrabHandlePosition position) {
+  return (position & GrabHandlePosition::kBottom);
+}
+
+// static
+bool DesignerExample::GrabHandle::IsLeft(GrabHandlePosition position) {
+  return (position & GrabHandlePosition::kLeft);
+}
+
+// static
+bool DesignerExample::GrabHandle::IsRight(GrabHandlePosition position) {
+  return (position & GrabHandlePosition::kRight);
+}
+
+BEGIN_METADATA(DesignerExample, GrabHandle, View)
+END_METADATA
+
+DesignerExample::GrabHandles::GrabHandles() = default;
+
+DesignerExample::GrabHandles::~GrabHandles() = default;
+
+void DesignerExample::GrabHandles::Initialize(View* layout_panel) {
+  static constexpr GrabHandlePosition positions[] = {
+      GrabHandlePosition::kTop,        GrabHandlePosition::kBottom,
+      GrabHandlePosition::kLeft,       GrabHandlePosition::kRight,
+      GrabHandlePosition::kTopLeft,    GrabHandlePosition::kTopRight,
+      GrabHandlePosition::kBottomLeft, GrabHandlePosition::kBottomRight,
+  };
+  DCHECK(grab_handles_.empty());
+  for (GrabHandlePosition position : positions) {
+    auto grab_handle = std::make_unique<GrabHandle>(this, position);
+    grab_handle->SizeToPreferredSize();
+    grab_handle->SetVisible(false);
+    grab_handles_.push_back(layout_panel->AddChildView(std::move(grab_handle)));
+  }
+}
+
+void DesignerExample::GrabHandles::SetAttachedView(View* view) {
+  for (GrabHandle* grab_handle : grab_handles_)
+    grab_handle->SetAttachedView(view);
+}
+
+bool DesignerExample::GrabHandles::IsGrabHandle(View* view) {
+  return base::ranges::find(grab_handles_, view) != grab_handles_.end();
+}
+
+DesignerExample::DesignerExample() : ExampleBase("Designer") {}
+
+DesignerExample::~DesignerExample() = default;
+
+void DesignerExample::CreateExampleView(View* container) {
+  Builder<View>(container)
+      .SetUseDefaultFillLayout(true)
+      .AddChildren(
+          Builder<BoxLayoutView>()
+              .CopyAddressTo(&designer_container_)
+              .SetOrientation(BoxLayout::Orientation::kHorizontal)
+              .SetMainAxisAlignment(BoxLayout::MainAxisAlignment::kEnd)
+              .SetCrossAxisAlignment(BoxLayout::CrossAxisAlignment::kStretch)
+              .AddChildren(
+                  Builder<DesignerSurface>()
+                      .CopyAddressTo(&designer_panel_)
+                      .CustomConfigure(base::BindOnce(
+                          [](DesignerExample* designer_example,
+                             DesignerSurface* designer_surface) {
+                            designer_surface->AddPreTargetHandler(
+                                designer_example);
+                          },
+                          base::Unretained(this))),
+                  Builder<BoxLayoutView>()
+                      .CopyAddressTo(&palette_panel_)
+                      .SetOrientation(BoxLayout::Orientation::kVertical)
+                      .SetInsideBorderInsets(gfx::Insets::TLBR(0, 3, 0, 0))
+                      .SetBetweenChildSpacing(3)
+                      .AddChildren(
+                          Builder<Combobox>()
+                              .CopyAddressTo(&view_type_)
+                              .SetAccessibleName(u"View Type")
+                              .SetModel(this),
+                          Builder<MdTextButton>()
+                              .SetCallback(base::BindRepeating(
+                                  &DesignerExample::CreateView,
+                                  base::Unretained(this)))
+                              .SetText(u"Add"),
+                          Builder<ScrollView>()
+                              .CustomConfigure(base::BindOnce(
+                                  [](DesignerExample* designer_example,
+                                     ScrollView* scroll_view) {
+                                    std::vector<ui::TableColumn> columns = {
+                                        MakeColumn(0, u"Name", true),
+                                        MakeColumn(1, u"Value", false)};
+                                    auto inspector =
+                                        std::make_unique<TableView>(
+                                            designer_example, columns,
+                                            views::TEXT_ONLY, true);
+                                    designer_example->inspector_ =
+                                        scroll_view->SetContents(
+                                            std::move(inspector));
+                                  },
+                                  base::Unretained(this)))
+                              .SetPreferredSize(gfx::Size(250, 400)))))
+      .BuildChildren();
+  grab_handles_.Initialize(designer_panel_);
+  designer_container_->SetFlexForView(designer_panel_, 75);
+  class_registrations_ = GetClassRegistrations();
+}
+
+void DesignerExample::OnEvent(ui::Event* event) {
+  if (event->IsMouseEvent() && event->target()) {
+    View* view = static_cast<View*>(event->target());
+    if (IsViewParent(designer_panel_, view->parent()) ||
+        view == designer_panel_) {
+      HandleDesignerMouseEvent(event);
+      return;
+    }
+  }
+  ui::EventHandler::OnEvent(event);
+}
+
+void DesignerExample::HandleDesignerMouseEvent(ui::Event* event) {
+  ui::MouseEvent* mouse_event = event->AsMouseEvent();
+  switch (mouse_event->type()) {
+    case ui::ET_MOUSE_PRESSED:
+      if (mouse_event->IsOnlyLeftMouseButton()) {
+        DCHECK(!dragging_);
+        View* event_view = GetDesignerChild(static_cast<View*>(event->target()),
+                                            designer_panel_);
+        if (grab_handles_.IsGrabHandle(event_view)) {
+          dragging_ = event_view;
+          return;
+        }
+        grab_handles_.SetAttachedView(nullptr);
+        if (event_view == designer_panel_) {
+          SelectView(nullptr);
+          return;
+        }
+        SelectView(event_view);
+        dragging_ = selected_;
+        last_mouse_pos_ = mouse_event->location();
+        event->SetHandled();
+        return;
+      }
+      break;
+    case ui::ET_MOUSE_DRAGGED:
+      if (dragging_) {
+        if (grab_handles_.IsGrabHandle(dragging_))
+          return;
+        gfx::Point new_position =
+            selected_->origin() +
+            SnapToGrid(mouse_event->location() - last_mouse_pos_);
+        new_position.SetToMax(gfx::Point());
+        new_position.SetToMin(designer_panel_->GetLocalBounds().bottom_right() -
+                              gfx::Vector2d(dragging_->size().width(),
+                                            dragging_->size().height()));
+        dragging_->SetPosition(new_position);
+        event->SetHandled();
+        return;
+      }
+      break;
+    case ui::ET_MOUSE_RELEASED:
+      grab_handles_.SetAttachedView(selected_);
+      if (dragging_) {
+        bool dragging_handle = grab_handles_.IsGrabHandle(dragging_);
+        dragging_ = nullptr;
+        if (!dragging_handle)
+          event->SetHandled();
+        return;
+      }
+      break;
+    default:
+      return;
+  }
+}
+
+void DesignerExample::SelectView(View* view) {
+  if (view != selected_) {
+    selected_ = view;
+    selected_members_.clear();
+    if (selected_) {
+      for (auto* member : *selected_->GetClassMetaData())
+        selected_members_.push_back(member);
+    }
+    if (model_observer_)
+      model_observer_->OnModelChanged();
+  }
+}
+
+gfx::Vector2d DesignerExample::SnapToGrid(const gfx::Vector2d& distance) {
+  return gfx::Vector2d(
+      SnapToInterval(distance.x(), designer_panel_->GetGridSize()),
+      SnapToInterval(distance.y(), designer_panel_->GetGridSize()));
+}
+
+void DesignerExample::CreateView(const ui::Event& event) {
+  std::unique_ptr<View> new_view =
+      class_registrations_[view_type_->GetSelectedRow()]->CreateView();
+  new_view->SizeToPreferredSize();
+  gfx::Rect child_rect = designer_panel_->GetContentsBounds();
+  child_rect.ClampToCenteredSize(new_view->size());
+  child_rect.set_origin(gfx::Point() +
+                        SnapToGrid(child_rect.OffsetFromOrigin()));
+  new_view->SetBoundsRect(child_rect);
+  designer_panel_->AddChildView(std::move(new_view));
+}
+
+int DesignerExample::RowCount() {
+  return selected_ ? selected_members_.size() : 0;
+}
+
+std::u16string DesignerExample::GetText(int row, int column_id) {
+  if (selected_) {
+    ui::metadata::MemberMetaDataBase* member = selected_members_[row];
+    if (column_id == 0)
+      return base::ASCIIToUTF16(member->member_name());
+    return member->GetValueAsString(selected_);
+  }
+  return std::u16string();
+}
+
+void DesignerExample::SetObserver(ui::TableModelObserver* observer) {
+  model_observer_ = observer;
+}
+
+int DesignerExample::GetItemCount() const {
+  return class_registrations_.size();
+}
+
+std::u16string DesignerExample::GetItemAt(int index) const {
+  return class_registrations_[index]->GetViewClassName();
+}
+
+int DesignerExample::GetDefaultIndex() const {
+  return 0;
+}
+
+}  // namespace views::examples
diff --git a/ui/views/examples/designer_example.h b/ui/views/examples/designer_example.h
new file mode 100644
index 0000000..8dc81c0
--- /dev/null
+++ b/ui/views/examples/designer_example.h
@@ -0,0 +1,171 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_EXAMPLES_DESIGNER_EXAMPLE_H_
+#define UI_VIEWS_EXAMPLES_DESIGNER_EXAMPLE_H_
+
+#include <memory>
+#include <vector>
+
+#include "third_party/skia/include/core/SkPath.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_types.h"
+#include "ui/base/models/combobox_model.h"
+#include "ui/base/models/table_model.h"
+#include "ui/events/event_handler.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/vector2d.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/examples/example_base.h"
+#include "ui/views/masked_targeter_delegate.h"
+#include "ui/views/view.h"
+
+namespace ui {
+class Event;
+}
+
+namespace gfx {
+class Vector2d;
+}
+
+namespace views {
+
+class BoxLayoutView;
+class Combobox;
+class TableView;
+
+namespace examples {
+
+class DesignerSurface;
+
+class BaseClassRegistration {
+ public:
+  virtual ~BaseClassRegistration();
+  virtual std::unique_ptr<View> CreateView() = 0;
+  virtual std::u16string GetViewClassName() = 0;
+};
+
+// DesignerExample. Demonstrates a simple visual designer for creating, placing,
+// moving and sizing individual views on a surface.
+class VIEWS_EXAMPLES_EXPORT DesignerExample : public ExampleBase,
+                                              public ui::TableModel,
+                                              public ui::ComboboxModel,
+                                              public ui::EventHandler {
+ public:
+  enum GrabHandlePosition : int {
+    kTop = 0x01,
+    kBottom = 0x02,
+    kLeft = 0x04,
+    kRight = 0x08,
+    kTopLeft = kTop | kLeft,
+    kTopRight = kTop | kRight,
+    kBottomLeft = kBottom | kLeft,
+    kBottomRight = kBottom | kRight,
+  };
+
+  static constexpr int kGrabHandleSize = 8;
+
+  class GrabHandles;
+
+  class GrabHandle : public View {
+   public:
+    METADATA_HEADER(GrabHandle);
+    GrabHandle(GrabHandles* grab_handles, GrabHandlePosition position);
+    GrabHandle(const GrabHandle&) = delete;
+    GrabHandle& operator=(const GrabHandle&) = delete;
+    ~GrabHandle() override;
+
+    void SetAttachedView(View* view);
+    View* attached_view() { return attached_view_; }
+    const View* attached_view() const { return attached_view_; }
+    GrabHandlePosition position() const { return position_; }
+    void UpdatePosition(bool reorder);
+
+   protected:
+    // View overrides.
+    gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override;
+    gfx::Size CalculatePreferredSize() const override;
+    void OnPaint(gfx::Canvas* canvas) override;
+    bool OnMousePressed(const ui::MouseEvent& event) override;
+    bool OnMouseDragged(const ui::MouseEvent& event) override;
+
+   private:
+    friend class DesignerExample;
+    void PositionOnView();
+    void UpdateViewSize();
+    static bool IsTop(GrabHandlePosition position);
+    static bool IsBottom(GrabHandlePosition position);
+    static bool IsLeft(GrabHandlePosition position);
+    static bool IsRight(GrabHandlePosition position);
+
+    GrabHandlePosition position_;
+    GrabHandles* grab_handles_;
+    View* attached_view_ = nullptr;
+    gfx::Point mouse_drag_pos_;
+  };
+
+  class GrabHandles {
+   public:
+    GrabHandles();
+    ~GrabHandles();
+
+    void Initialize(View* layout_panel);
+    void SetAttachedView(View* view);
+    bool IsGrabHandle(View* view);
+
+   private:
+    std::vector<GrabHandle*> grab_handles_;
+  };
+
+  DesignerExample();
+  DesignerExample(const DesignerExample&) = delete;
+  DesignerExample& operator=(const DesignerExample&) = delete;
+  ~DesignerExample() override;
+
+ protected:
+  // ExampleBase overrides
+  void CreateExampleView(View* container) override;
+
+  // ui::EventHandler overrides
+  void OnEvent(ui::Event* event) override;
+
+ private:
+  void HandleDesignerMouseEvent(ui::Event* event);
+  void SelectView(View* view);
+  gfx::Vector2d SnapToGrid(const gfx::Vector2d& distance);
+  // Creates the selected view class.
+  void CreateView(const ui::Event& event);
+
+  // ui::TableModel overrides
+  int RowCount() override;
+  std::u16string GetText(int row, int column_id) override;
+  void SetObserver(ui::TableModelObserver* observer) override;
+
+  // ui::ComboboxModel overrides
+  int GetItemCount() const override;
+  std::u16string GetItemAt(int index) const override;
+  int GetDefaultIndex() const override;
+
+  BoxLayoutView* designer_container_ = nullptr;
+  DesignerSurface* designer_panel_ = nullptr;
+  View* palette_panel_ = nullptr;
+
+  Combobox* view_type_ = nullptr;
+  TableView* inspector_ = nullptr;
+  ui::TableModelObserver* model_observer_ = nullptr;
+
+  View* selected_ = nullptr;
+  View* dragging_ = nullptr;
+  gfx::Point last_mouse_pos_;
+  std::vector<ui::metadata::MemberMetaDataBase*> selected_members_;
+
+  GrabHandles grab_handles_;
+
+  std::vector<std::unique_ptr<BaseClassRegistration>> class_registrations_;
+};
+
+}  // namespace examples
+}  // namespace views
+
+#endif  // UI_VIEWS_EXAMPLES_DESIGNER_EXAMPLE_H_
diff --git a/ui/views/examples/examples_color_id.h b/ui/views/examples/examples_color_id.h
index 956d86a..c6742a5 100644
--- a/ui/views/examples/examples_color_id.h
+++ b/ui/views/examples/examples_color_id.h
@@ -18,6 +18,8 @@
   E_CPONLY(kColorBubbleExampleBackground3) \
   E_CPONLY(kColorBubbleExampleBackground4) \
   E_CPONLY(kColorButtonExampleBackground) \
+  E_CPONLY(kColorDesignerGrabHandle) \
+  E_CPONLY(kColorDesignerGrid) \
   E_CPONLY(kColorFadeAnimationExampleBackground) \
   E_CPONLY(kColorFadeAnimationExampleBorder) \
   E_CPONLY(kColorFadeAnimationExampleForeground) \
diff --git a/ui/views/examples/examples_color_mixer.cc b/ui/views/examples/examples_color_mixer.cc
index 743f108..b5544a6 100644
--- a/ui/views/examples/examples_color_mixer.cc
+++ b/ui/views/examples/examples_color_mixer.cc
@@ -27,6 +27,8 @@
   mixer[Ids::kColorBubbleExampleBackground4] = {
       SkColorSetRGB(0xC1, 0xB1, 0xE1)};
   mixer[Ids::kColorButtonExampleBackground] = {SK_ColorWHITE};
+  mixer[Ids::kColorDesignerGrabHandle] = {gfx::kGoogleGrey500};
+  mixer[Ids::kColorDesignerGrid] = {SK_ColorBLACK};
   mixer[Ids::kColorFadeAnimationExampleBorder] = {gfx::kGoogleGrey900};
   mixer[Ids::kColorFadeAnimationExampleBackground] = {SK_ColorWHITE};
   mixer[Ids::kColorFadeAnimationExampleForeground] = {gfx::kGoogleBlue800};
diff --git a/ui/views/native_cursor.h b/ui/views/native_cursor.h
index 81f6e21..6e01b2d 100644
--- a/ui/views/native_cursor.h
+++ b/ui/views/native_cursor.h
@@ -15,6 +15,8 @@
 VIEWS_EXPORT gfx::NativeCursor GetNativeColumnResizeCursor();
 VIEWS_EXPORT gfx::NativeCursor GetNativeEastWestResizeCursor();
 VIEWS_EXPORT gfx::NativeCursor GetNativeNorthSouthResizeCursor();
+VIEWS_EXPORT gfx::NativeCursor GetNativeNorthWestSouthEastResizeCursor();
+VIEWS_EXPORT gfx::NativeCursor GetNativeNorthEastSouthWestResizeCursor();
 
 }  // namespace views
 
diff --git a/ui/views/native_cursor_aura.cc b/ui/views/native_cursor_aura.cc
index bd346bb..d9b86c31 100644
--- a/ui/views/native_cursor_aura.cc
+++ b/ui/views/native_cursor_aura.cc
@@ -29,4 +29,12 @@
   return ui::mojom::CursorType::kNorthSouthResize;
 }
 
+gfx::NativeCursor GetNativeNorthWestSouthEastResizeCursor() {
+  return ui::mojom::CursorType::kNorthWestSouthEastResize;
+}
+
+gfx::NativeCursor GetNativeNorthEastSouthWestResizeCursor() {
+  return ui::mojom::CursorType::kNorthEastSouthWestResize;
+}
+
 }  // namespace views
diff --git a/ui/views/native_cursor_mac.mm b/ui/views/native_cursor_mac.mm
index 9d9c1c4..059de768 100644
--- a/ui/views/native_cursor_mac.mm
+++ b/ui/views/native_cursor_mac.mm
@@ -38,4 +38,16 @@
   return [NSCursor resizeUpDownCursor];
 }
 
+gfx::NativeCursor GetNativeNorthWestSouthEastResizeCursor() {
+  NOTIMPLEMENTED();
+  // TODO(tapted): This is the wrong cursor. Fetch the right one from WebCursor
+  // or ResourceBundle or CoreCursor private API.
+  return [NSCursor resizeLeftRightCursor];
+}
+
+gfx::NativeCursor GetNativeNorthEastSouthWestResizeCursor() {
+  NOTIMPLEMENTED();
+  return [NSCursor resizeUpDownCursor];
+}
+
 }  // namespace views
diff --git a/url/BUILD.gn b/url/BUILD.gn
index 8d260a4..1b16946 100644
--- a/url/BUILD.gn
+++ b/url/BUILD.gn
@@ -130,7 +130,10 @@
 
   android_library("url_java") {
     sources = [ "android/java/src/org/chromium/url/IDNStringUtil.java" ]
-    deps = [ "//base:base_java" ]
+    deps = [
+      "//base:base_java",
+      "//build/android:build_java",
+    ]
   }
 
   android_library("gurl_java") {
@@ -141,6 +144,7 @@
     ]
     deps = [
       "//base:base_java",
+      "//build/android:build_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
     ]
     annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
@@ -294,6 +298,7 @@
       ":gurl_java",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
     ]
   }
 
@@ -331,6 +336,7 @@
       ":gurl_junit_test_support",
       "//base:base_java",
       "//base:base_java_test_support",
+      "//build/android:build_java",
       "//content/public/test/android:content_java_test_support",
       "//third_party/android_support_test_runner:rules_java",
       "//third_party/android_support_test_runner:runner_java",
@@ -363,6 +369,7 @@
       "//base:base_java_test_support",
       "//base:base_junit_test_support",
       "//base/test:test_support_java",
+      "//build/android:build_java",
       "//third_party/android_deps:robolectric_all_java",
       "//third_party/junit",
     ]
diff --git a/weblayer/browser/android/javatests/BUILD.gn b/weblayer/browser/android/javatests/BUILD.gn
index f41e1b58..6b7fce7 100644
--- a/weblayer/browser/android/javatests/BUILD.gn
+++ b/weblayer/browser/android/javatests/BUILD.gn
@@ -51,6 +51,7 @@
     ":weblayer_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//components/browser_ui/share/android:java",
     "//components/safe_browsing/android:safe_browsing_java",
     "//content/public/android:content_java",
@@ -105,6 +106,7 @@
     ":weblayer_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/android:content_java",
     "//content/public/test/android:content_java_test_support",
     "//net/android:net_java_test_support",
@@ -145,6 +147,7 @@
   deps = [
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/test/android:content_java_test_support",
     "//net/android:net_java_test_support",
     "//third_party/android_support_test_runner:rules_java",
@@ -168,6 +171,7 @@
     ":weblayer_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/hamcrest:hamcrest_java",
@@ -321,6 +325,7 @@
     ":weblayer_java_test_support",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn
index 6bbf11d..8bd2c828 100644
--- a/weblayer/browser/java/BUILD.gn
+++ b/weblayer/browser/java/BUILD.gn
@@ -107,6 +107,7 @@
     ":base_module_interfaces_java",
     "$google_play_services_package:google_play_services_basement_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/embedder_support/android:application_java",
     "//content/public/android:content_java",
   ]
@@ -211,6 +212,7 @@
     ":weblayer_bundle_utils",
     ":weblayer_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//cc:cc_java",
     "//components/android_autofill/browser:java",
     "//components/autofill_assistant/android:public_dependencies_java",
@@ -376,6 +378,7 @@
     ":test_interfaces_java",
     ":weblayer_test_resources",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/android_autofill/browser:java",
     "//components/android_autofill/browser/test_support:component_autofill_provider_java_test_support",
     "//components/browser_ui/accessibility/android:java",
@@ -407,6 +410,7 @@
   deps = [
     ":java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/payments/content/android:java",
     "//components/payments/content/android:junit_test_support",
     "//components/payments/content/android:service_java",
@@ -438,6 +442,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//build/android:build_java",
     "//components/payments/content/android:java",
     "//components/payments/content/android:junit_test_support",
     "//components/payments/content/android:service_java",
diff --git a/weblayer/browser/webapps/webapk_install_scheduler.cc b/weblayer/browser/webapps/webapk_install_scheduler.cc
index 8a6f4d70..4479585 100644
--- a/weblayer/browser/webapps/webapk_install_scheduler.cc
+++ b/weblayer/browser/webapps/webapk_install_scheduler.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "base/bind.h"
-#include "base/task/post_task.h"
 #include "base/task/task_runner_util.h"
 #include "base/task/thread_pool.h"
 #include "components/webapps/browser/android/shortcut_info.h"
diff --git a/weblayer/public/javatests/BUILD.gn b/weblayer/public/javatests/BUILD.gn
index e7453c3..36fdd8b 100644
--- a/weblayer/public/javatests/BUILD.gn
+++ b/weblayer/public/javatests/BUILD.gn
@@ -14,6 +14,7 @@
   deps = [
     "//base:base_java",
     "//base:base_java_test_support",
+    "//build/android:build_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/junit:junit",
diff --git a/weblayer/shell/android/BUILD.gn b/weblayer/shell/android/BUILD.gn
index 15d4678b..11f1d256 100644
--- a/weblayer/shell/android/BUILD.gn
+++ b/weblayer/shell/android/BUILD.gn
@@ -44,6 +44,7 @@
     ":weblayer_shell_resources",
     "$google_play_services_package:google_play_services_base_java",
     "//base:base_java",
+    "//build/android:build_java",
     "//components/strictmode/android:java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
@@ -236,6 +237,7 @@
     "//android_webview:pak_file_assets",
     "//android_webview:weblayer_webview_assets",
     "//base:base_java",
+    "//build/android:build_java",
     "//weblayer:locale_pak_assets",
     "//weblayer/browser/java",
     "//weblayer/browser/java:test_java",
diff --git a/weblayer/test/BUILD.gn b/weblayer/test/BUILD.gn
index 39373bd8..b3b9a32 100644
--- a/weblayer/test/BUILD.gn
+++ b/weblayer/test/BUILD.gn
@@ -38,6 +38,7 @@
       "//base:base_java",
       "//base:base_java_test_support",
       "//base:jni_java",
+      "//build/android:build_java",
       "//components/embedder_support/android:application_java",
       "//components/safe_browsing/android:safe_browsing_java",
       "//components/translate/content/android:java",