diff --git a/DEPS b/DEPS
index 6f6a8936..366bb339 100644
--- a/DEPS
+++ b/DEPS
@@ -280,19 +280,19 @@
   # 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': '707fc031f19492c881e27f8ac40dd2189056e036',
+  'skia_revision': 'df4a82a524165981c041c20d749c929a1fa9ba66',
   # 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': '166893317c929b1d3049738059221d0f661f3f33',
+  'v8_revision': '04ed801ac6ab0ad3a8d16774165fc9a8ce28d060',
   # 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': 'fd1317a7046ad645cd6cfab99bd64a62c014f323',
+  'angle_revision': 'f1c21d688b82349cb2e3dd9daad80285e2a0a3e6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '278fbb8f9b7512f18ee81f88e49ff39f72e093f5',
+  'swiftshader_revision': '94c736299c3899ef3bacf5a9e1a444aeaa15c785',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -307,7 +307,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:8.20220613.2.1',
+  'fuchsia_version': 'version:8.20220613.3.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -351,7 +351,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'b3e527ac6f02a37b41b110c6d729db4d3211aaeb',
+  'catapult_revision': 'd854027b5cff510baf7a712c900474d01b1c0701',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -395,11 +395,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '06cc5c1acdf3f27266683900e4712690867704c9',
+  'dawn_revision': '8cc184ea594fb8b900b9070cea5ca7f0006550f7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '360aad190f7013ad7c47fde70f149e41f318bb10',
+  'quiche_revision': '815e726bf50ad77a13d219e06a9721a5f3faf370',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -439,7 +439,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'libcxxabi_revision':    '013bcd820a353ec1d3ff472f2971553fea7232cf',
+  'libcxxabi_revision':    'bb4dcb7164a67f828225714c7ed099cfe418d3d7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1141,7 +1141,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '544594e0b2760e2ded229d6b06782f01d82b0a6c',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b6030901cf9d3caf29ba534ae1d96426e0e90a22',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1538,7 +1538,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '5ec4fc1b905f3b329bc01010ad5f49f71d4cffba',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '5fb67c4d2c82a17bf682d715662b4ab3e37116c9',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1708,7 +1708,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '6f515f3d7aa74d9424fdc3e28db1e9cefb56b46e',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'dcb9c5d43f28800089209f48cc573518bc006cf2',
+    Var('webrtc_git') + '/src.git' + '@' + '1bf9c5e1ed7b4afde9b204178fa55274969f3ff8',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1822,7 +1822,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': '0MSY234BIwHRlYrXOQNnFK_XgdpGmsR0SCICI38ggzYC',
+        'version': 'fh-fgZtda41SvFJJkuWG7HD4e_J7YfUR0hCipRPCZWwC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc
index 0edb16b..f4beb27 100644
--- a/ash/accelerators/accelerator_controller_impl.cc
+++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -816,7 +816,7 @@
     // toggle the AppList in that case. Check for VKEY_SHIFT because this is
     // used to show fullscreen app list.
     if (key != ui::VKEY_LWIN && key != ui::VKEY_SHIFT &&
-        key != ui::VKEY_BROWSER_SEARCH) {
+        key != ui::VKEY_BROWSER_SEARCH && key != ui::VKEY_ALL_APPLICATIONS) {
       return false;
     }
   }
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index 27eb90f..9bf8f0ee 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -1394,20 +1394,41 @@
   EXPECT_FALSE(tray->IsBubbleShown());
 }
 
-TEST_F(AcceleratorControllerTest,
-       GlobalAcceleratorsToggleProductivityLauncher) {
+class GlobalAcceleratorsToggleProductivityLauncher
+    : public AcceleratorControllerTest,
+      public testing::WithParamInterface<
+          std::pair<ui::KeyboardCode, ui::Accelerator::KeyState>> {
+ public:
+  GlobalAcceleratorsToggleProductivityLauncher() {
+    std::tie(key_, key_state_) = GetParam();
+  }
+
+ protected:
+  ui::KeyboardCode key_;
+  ui::Accelerator::KeyState key_state_;
+};
+
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    GlobalAcceleratorsToggleProductivityLauncher,
+    testing::Values(std::make_pair(ui::VKEY_LWIN,
+                                   ui::Accelerator::KeyState::RELEASED),
+                    std::make_pair(ui::VKEY_BROWSER_SEARCH,
+                                   ui::Accelerator::KeyState::PRESSED),
+                    std::make_pair(ui::VKEY_ALL_APPLICATIONS,
+                                   ui::Accelerator::KeyState::PRESSED)));
+
+TEST_P(GlobalAcceleratorsToggleProductivityLauncher, ToggleLauncher) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitAndEnableFeature(features::kProductivityLauncher);
 
-  // Search key opens the launcher.
-  EXPECT_TRUE(ProcessInController(
-      ui::Accelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_NONE)));
+  EXPECT_TRUE(
+      ProcessInController(ui::Accelerator(key_, ui::EF_NONE, key_state_)));
   base::RunLoop().RunUntilIdle();
   GetAppListTestHelper()->CheckVisibility(true);
 
-  // Search key again closes the launcher.
-  EXPECT_TRUE(ProcessInController(
-      ui::Accelerator(ui::VKEY_BROWSER_SEARCH, ui::EF_NONE)));
+  EXPECT_TRUE(
+      ProcessInController(ui::Accelerator(key_, ui::EF_NONE, key_state_)));
   base::RunLoop().RunUntilIdle();
   GetAppListTestHelper()->CheckVisibility(false);
 }
diff --git a/ash/components/arc/appfuse/arc_appfuse_bridge.cc b/ash/components/arc/appfuse/arc_appfuse_bridge.cc
index 0386fcb8..0195798c 100644
--- a/ash/components/arc/appfuse/arc_appfuse_bridge.cc
+++ b/ash/components/arc/appfuse/arc_appfuse_bridge.cc
@@ -13,7 +13,6 @@
 #include "base/bind.h"
 #include "base/memory/singleton.h"
 #include "chromeos/dbus/arc/arc_appfuse_provider_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
 namespace arc {
@@ -83,16 +82,16 @@
 void ArcAppfuseBridge::Mount(uint32_t uid,
                              int32_t mount_id,
                              MountCallback callback) {
-  // This is always safe because DBusThreadManager outlives ArcServiceLauncher.
-  chromeos::DBusThreadManager::Get()->GetArcAppfuseProviderClient()->Mount(
+  // This is safe because ArcAppfuseProviderClient outlives ArcServiceLauncher.
+  chromeos::ArcAppfuseProviderClient::Get()->Mount(
       uid, mount_id, base::BindOnce(&RunWithScopedHandle, std::move(callback)));
 }
 
 void ArcAppfuseBridge::Unmount(uint32_t uid,
                                int32_t mount_id,
                                UnmountCallback callback) {
-  chromeos::DBusThreadManager::Get()->GetArcAppfuseProviderClient()->Unmount(
-      uid, mount_id, std::move(callback));
+  chromeos::ArcAppfuseProviderClient::Get()->Unmount(uid, mount_id,
+                                                     std::move(callback));
 }
 
 void ArcAppfuseBridge::OpenFile(uint32_t uid,
@@ -100,7 +99,7 @@
                                 int32_t file_id,
                                 int32_t flags,
                                 OpenFileCallback callback) {
-  chromeos::DBusThreadManager::Get()->GetArcAppfuseProviderClient()->OpenFile(
+  chromeos::ArcAppfuseProviderClient::Get()->OpenFile(
       uid, mount_id, file_id, flags,
       base::BindOnce(&RunWithScopedHandle, std::move(callback)));
 }
diff --git a/ash/components/fwupd/firmware_update_manager.h b/ash/components/fwupd/firmware_update_manager.h
index 32a3e113..697d190 100644
--- a/ash/components/fwupd/firmware_update_manager.h
+++ b/ash/components/fwupd/firmware_update_manager.h
@@ -81,6 +81,9 @@
   // Gets the global instance pointer.
   static FirmwareUpdateManager* Get();
 
+  // Gets the number of cached updates.
+  size_t GetUpdateCount() { return updates_.size(); }
+
   // FwupdClient::Observer:
   // When the fwupd DBus client gets a response with devices from fwupd,
   // it calls this function and passes the response.
@@ -172,8 +175,6 @@
     fake_url_for_testing_ = fake_url;
   }
 
-  int GetNumUpdatesForTesting() { return updates_.size(); }
-
   // Resets the mojo::Receiver |install_controller_receiver_|
   // and |update_progress_observer_|.
   void ResetInstallState();
diff --git a/ash/components/fwupd/firmware_update_manager_unittest.cc b/ash/components/fwupd/firmware_update_manager_unittest.cc
index 1306f63f..7a9def8 100644
--- a/ash/components/fwupd/firmware_update_manager_unittest.cc
+++ b/ash/components/fwupd/firmware_update_manager_unittest.cc
@@ -204,10 +204,6 @@
     loop.Run();
   }
 
-  int GetNumUpdatesCached() {
-    return firmware_update_manager_->GetNumUpdatesForTesting();
-  }
-
   void RequestDevices() {
     firmware_update_manager_->RequestDevices();
     base::RunLoop().RunUntilIdle();
@@ -588,6 +584,7 @@
       update_observer.updates();
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(updates.empty());
+  ASSERT_EQ(0U, firmware_update_manager_->GetUpdateCount());
 }
 
 TEST_F(FirmwareUpdateManagerTest, RequestAllUpdatesOneDeviceNoUpdates) {
@@ -603,6 +600,7 @@
 
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(updates.empty());
+  ASSERT_EQ(0U, firmware_update_manager_->GetUpdateCount());
 }
 
 TEST_F(FirmwareUpdateManagerTest, RequestAllUpdatesOneDeviceOneUpdate) {
@@ -618,6 +616,7 @@
 
   base::RunLoop().RunUntilIdle();
   ASSERT_EQ(1U, updates.size());
+  ASSERT_EQ(1U, firmware_update_manager_->GetUpdateCount());
   EXPECT_EQ(kFakeDeviceIdForTesting, updates[0]->device_id);
   EXPECT_EQ(base::UTF8ToUTF16(std::string(kFakeDeviceNameForTesting)),
             updates[0]->device_name);
@@ -643,7 +642,7 @@
 
   base::RunLoop().RunUntilIdle();
   ASSERT_EQ(1U, updates.size());
-  ASSERT_EQ(1, GetNumUpdatesCached());
+  ASSERT_EQ(1U, firmware_update_manager_->GetUpdateCount());
 
   dbus_responses_.push_back(CreateOneDeviceResponse());
   dbus_responses_.push_back(CreateOneUpdateResponse());
@@ -654,7 +653,7 @@
   const std::vector<firmware_update::mojom::FirmwareUpdatePtr>& new_updates =
       update_observer.updates();
   ASSERT_EQ(1U, new_updates.size());
-  ASSERT_EQ(1, GetNumUpdatesCached());
+  ASSERT_EQ(1U, firmware_update_manager_->GetUpdateCount());
 }
 
 TEST_F(FirmwareUpdateManagerTest, RequestAllUpdatesTwoDeviceOneWithUpdate) {
@@ -673,6 +672,7 @@
 
   base::RunLoop().RunUntilIdle();
   ASSERT_EQ(1U, updates.size());
+  ASSERT_EQ(1U, firmware_update_manager_->GetUpdateCount());
 
   // The second device was the one with the update.
   EXPECT_EQ(std::string(kFakeDeviceIdForTesting) + "2", updates[0]->device_id);
@@ -703,6 +703,7 @@
   base::RunLoop().RunUntilIdle();
   ASSERT_EQ(1, update_observer.num_times_notified());
   ASSERT_EQ(1U, updates.size());
+  ASSERT_EQ(1U, firmware_update_manager_->GetUpdateCount());
 
   // Request all updates multiple times, this time while a request is already
   // being made.
diff --git a/ash/system/time/calendar_view.cc b/ash/system/time/calendar_view.cc
index cdbbfb9..d57787c 100644
--- a/ash/system/time/calendar_view.cc
+++ b/ash/system/time/calendar_view.cc
@@ -798,22 +798,26 @@
 }
 
 void CalendarView::ScrollToToday() {
-  {
-    base::AutoReset<bool> is_resetting_scrolling(&is_resetting_scroll_, true);
-    scroll_view_->ScrollToPosition(scroll_view_->vertical_scroll_bar(),
-                                   PositionOfCurrentMonth());
+  base::AutoReset<bool> is_resetting_scrolling(&is_resetting_scroll_, true);
+
+  if (event_list_view_) {
+    scroll_view_->ScrollToPosition(
+        scroll_view_->vertical_scroll_bar(),
+        PositionOfToday() + kExpandedCalendarPadding);
+    return;
   }
 
+  scroll_view_->ScrollToPosition(scroll_view_->vertical_scroll_bar(),
+                                 PositionOfCurrentMonth());
+
   // If the screen does not have enough height which makes today's cell not in
   // the visible rect, we auto scroll to today's row instead of scrolling to the
   // first row of the current month.
   if (PositionOfCurrentMonth() +
           calendar_view_controller_->GetTodayRowBottomHeight() >
       scroll_view_->GetVisibleRect().bottom()) {
-    base::AutoReset<bool> is_resetting_scrolling(&is_resetting_scroll_, true);
-    scroll_view_->ScrollToPosition(
-        scroll_view_->vertical_scroll_bar(),
-        PositionOfToday() + (event_list_view_ ? kExpandedCalendarPadding : 0));
+    scroll_view_->ScrollToPosition(scroll_view_->vertical_scroll_bar(),
+                                   PositionOfToday());
   }
 }
 
diff --git a/ash/webui/guest_os_installer/DIR_METADATA b/ash/webui/guest_os_installer/DIR_METADATA
index b3cd940..06e627f 100644
--- a/ash/webui/guest_os_installer/DIR_METADATA
+++ b/ash/webui/guest_os_installer/DIR_METADATA
@@ -1,3 +1 @@
-monorail {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/ash/webui/os_feedback_ui/os_feedback_ui.cc b/ash/webui/os_feedback_ui/os_feedback_ui.cc
index 981928a..5a05e3a7 100644
--- a/ash/webui/os_feedback_ui/os_feedback_ui.cc
+++ b/ash/webui/os_feedback_ui/os_feedback_ui.cc
@@ -54,6 +54,8 @@
       {"attachFilesLabel", IDS_FEEDBACK_TOOL_ATTACH_FILES_LABEL},
       {"replaceFileLabel", IDS_FEEDBACK_TOOL_REPLACE_FILE_LABEL},
       {"userEmailLabel", IDS_FEEDBACK_TOOL_USER_EMAIL_LABEL},
+      {"shareDiagnosticDataLabel",
+       IDS_FEEDBACK_TOOL_SHARE_DIAGNOSTIC_DATA_LABEL},
       {"confirmationTitleOnline", IDS_FEEDBACK_TOOL_PAGE_TITLE_AFTER_SENT},
   };
 
diff --git a/ash/webui/os_feedback_ui/resources/share_data_page.html b/ash/webui/os_feedback_ui/resources/share_data_page.html
index 67f7664..10b8e02 100644
--- a/ash/webui/os_feedback_ui/resources/share_data_page.html
+++ b/ash/webui/os_feedback_ui/resources/share_data_page.html
@@ -103,7 +103,7 @@
     </div>
     <!-- Diagnostic data -->
     <div id="shareDiagnosticData">
-      <p>Share diagnostic data</p>
+      <p id="shareDiagnosticDataLabel">[[i18n('shareDiagnosticDataLabel')]]</p>
       <!-- URL -->
       <div id="pageUrl" class="checkbox-field-container">
         <input id="pageUrlCheckbox" type="checkbox" aria-labelledby="pageUrlLabel"
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 3d13052..9d7b8c7e 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1678,6 +1678,8 @@
       "android/reached_code_profiler.h",
       "android/record_histogram.cc",
       "android/record_user_action.cc",
+      "android/remove_stale_data.cc",
+      "android/remove_stale_data.h",
       "android/scoped_hardware_buffer_fence_sync.cc",
       "android/scoped_hardware_buffer_fence_sync.h",
       "android/scoped_hardware_buffer_handle.cc",
@@ -4381,9 +4383,7 @@
     sources = [ "test/android/javatests/src/org/chromium/base/process_launcher/TestChildProcessConnection.java" ]
   }
 
-  android_library("base_junit_test_support") {
-    # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-    bypass_platform_checks = true
+  robolectric_library("base_junit_test_support") {
     testonly = true
     sources = [
       "//third_party/robolectric/custom_asynctask/java/src/org/chromium/base/task/test/ShadowAsyncTask.java",
@@ -4404,7 +4404,6 @@
     deps = [
       ":base_java",
       "//testing/android/junit:junit_test_support",
-      "//third_party/android_deps:robolectric_all_java",
       "//third_party/android_support_test_runner:runner_java",
       "//third_party/androidx:androidx_test_core_java",
       "//third_party/hamcrest:hamcrest_java",
diff --git a/base/allocator/allocator.gni b/base/allocator/allocator.gni
index c3c62f8..97a57df 100644
--- a/base/allocator/allocator.gni
+++ b/base/allocator/allocator.gni
@@ -112,10 +112,7 @@
   # Finch.
   use_fake_binary_experiment = false
 
-  # The supported platforms are supposed to match `_is_brp_supported`, but we
-  # enable the feature on Linux early because it's most widely used for security
-  # research
-  use_asan_backup_ref_ptr = is_asan && (is_win || is_android || is_linux)
+  use_asan_backup_ref_ptr = false
 }
 
 # Prevent using BackupRefPtr when PartitionAlloc-Everywhere isn't used.
diff --git a/base/allocator/partition_alloc_features.cc b/base/allocator/partition_alloc_features.cc
index d37b2500..621f767b 100644
--- a/base/allocator/partition_alloc_features.cc
+++ b/base/allocator/partition_alloc_features.cc
@@ -55,8 +55,7 @@
 
 const Feature kPartitionAllocBackupRefPtr {
   "PartitionAllocBackupRefPtr",
-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || \
-    (BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) && BUILDFLAG(IS_LINUX))
+#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN)
       FEATURE_ENABLED_BY_DEFAULT
 #else
       FEATURE_DISABLED_BY_DEFAULT
diff --git a/base/android/junit/src/org/chromium/base/FileUtilsTest.java b/base/android/junit/src/org/chromium/base/FileUtilsTest.java
index 6559205c..9778a55b 100644
--- a/base/android/junit/src/org/chromium/base/FileUtilsTest.java
+++ b/base/android/junit/src/org/chromium/base/FileUtilsTest.java
@@ -9,8 +9,6 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.ContentProvider;
 import android.content.ContentValues;
 import android.content.Context;
@@ -468,8 +466,7 @@
         }
 
         @Override
-        public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode)
-                throws FileNotFoundException {
+        public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
             String uriString = uri.toString();
             if (mUriToFilename.containsKey(uriString)) {
                 String filename = mUriToFilename.get(uriString);
diff --git a/base/android/remove_stale_data.cc b/base/android/remove_stale_data.cc
new file mode 100644
index 0000000..521cd50
--- /dev/null
+++ b/base/android/remove_stale_data.cc
@@ -0,0 +1,57 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/remove_stale_data.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/trace_event/base_tracing.h"
+
+namespace base {
+namespace android {
+
+namespace {
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class DeleteResult {
+  kNotFound = 0,
+  kDeleted = 1,
+  kDeleteError = 2,
+  kMaxValue = kDeleteError,
+};
+
+void RecordDeleteResult(DeleteResult result) {
+  base::UmaHistogramEnumeration("NetworkService.ClearStaleDataDirectoryResult",
+                                result);
+}
+
+void RemoveStaleDataDirectoryOnPool(const base::FilePath& data_directory) {
+  TRACE_EVENT0("startup", "RemoveStaleDataDirectoryOnPool");
+  if (!base::PathExists(data_directory)) {
+    RecordDeleteResult(DeleteResult::kNotFound);
+    return;
+  }
+  if (base::DeletePathRecursively(data_directory)) {
+    RecordDeleteResult(DeleteResult::kDeleted);
+    return;
+  }
+  RecordDeleteResult(DeleteResult::kDeleteError);
+}
+
+}  // namespace
+
+void RemoveStaleDataDirectory(const base::FilePath& data_directory) {
+  base::ThreadPool::PostTask(
+      FROM_HERE,
+      {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
+       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+      base::BindOnce(&RemoveStaleDataDirectoryOnPool, data_directory));
+}
+
+}  // namespace android
+}  // namespace base
diff --git a/base/android/remove_stale_data.h b/base/android/remove_stale_data.h
new file mode 100644
index 0000000..7a4a634
--- /dev/null
+++ b/base/android/remove_stale_data.h
@@ -0,0 +1,25 @@
+// 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 BASE_ANDROID_REMOVE_STALE_DATA_H_
+#define BASE_ANDROID_REMOVE_STALE_DATA_H_
+
+#include "base/base_export.h"
+
+namespace base {
+
+class FilePath;
+
+namespace android {
+
+// Removes the `data_directory` with all its contents and records a histogram
+// allowing to estimate the rate of removals.
+// TODO(crbug.com/1331809): Remove this code after the data from the field shows
+// no removal is happening in practice, plus a few milestones.
+void BASE_EXPORT RemoveStaleDataDirectory(const base::FilePath& data_directory);
+
+}  // namespace android
+}  // namespace base
+
+#endif  // BASE_ANDROID_REMOVE_STALE_DATA_H_
diff --git a/build/android/gyp/compile_java.py b/build/android/gyp/compile_java.py
index d3fca590..37121a7 100755
--- a/build/android/gyp/compile_java.py
+++ b/build/android/gyp/compile_java.py
@@ -755,7 +755,7 @@
         options.java_version,
     ])
   if options.java_version == '1.8':
-    # Android's boot jar doesn't contain all java 8 classes.
+    # Android's boot jar doesn't contain all java classes.
     options.bootclasspath.append(build_utils.RT_JAR_PATH)
 
   # This effectively disables all annotation processors, even including
@@ -765,7 +765,12 @@
   javac_args.extend(['-proc:none'])
 
   if options.bootclasspath:
-    javac_args.extend(['-bootclasspath', ':'.join(options.bootclasspath)])
+    # if we are targeting source code higher than java 8, we cannot use
+    # -bootclasspath anymore (deprecated). Instead just prepend the classpath.
+    if options.java_version != '1.8':
+      options.classpath = options.bootclasspath + options.classpath
+    else:
+      javac_args.extend(['-bootclasspath', ':'.join(options.bootclasspath)])
 
   if options.processorpath:
     javac_args.extend(['-processorpath', ':'.join(options.processorpath)])
diff --git a/build/android/gyp/compile_resources.py b/build/android/gyp/compile_resources.py
index a7907b4..51491ed 100755
--- a/build/android/gyp/compile_resources.py
+++ b/build/android/gyp/compile_resources.py
@@ -409,9 +409,15 @@
     except build_utils.CalledProcessError:
       return None
 
-  android_sdk_jars = [j for j in options.include_resources
-                      if os.path.basename(j) in ('android.jar',
-                                                 'android_system.jar')]
+  def is_sdk_jar(jar_name):
+    if jar_name in ('android.jar', 'android_system.jar'):
+      return True
+    # Robolectric jar looks a bit different.
+    return 'android-all' in jar_name and 'robolectric' in jar_name
+
+  android_sdk_jars = [
+      j for j in options.include_resources if is_sdk_jar(os.path.basename(j))
+  ]
   extract_all = [maybe_extract_version(j) for j in android_sdk_jars]
   successful_extractions = [x for x in extract_all if x]
   if len(successful_extractions) == 0:
diff --git a/build/android/gyp/turbine.py b/build/android/gyp/turbine.py
index 247924b..2d71b13e 100755
--- a/build/android/gyp/turbine.py
+++ b/build/android/gyp/turbine.py
@@ -101,7 +101,7 @@
         options.java_version,
     ])
   if options.java_version == '1.8':
-    # Android's boot jar doesn't contain all java 8 classes.
+    # Android's boot jar doesn't contain all java classes.
     options.bootclasspath.append(build_utils.RT_JAR_PATH)
 
   if options.bootclasspath:
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index 3eadc97..71b1ca0 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -1057,6 +1057,11 @@
       action='store_true',
       help='True if a java library is not chromium code, used for lint.')
 
+  # robolectric_library options
+  parser.add_option('--is-robolectric',
+                    action='store_true',
+                    help='Whether this is a host side android test library.')
+
   # android library options
   parser.add_option('--dex-path', help='Path to target\'s dex output.')
 
@@ -1442,7 +1447,10 @@
     deps_info['requires_android'] = bool(options.requires_android)
     deps_info['supports_android'] = bool(options.supports_android)
 
-    if not options.bypass_platform_checks:
+    # robolectric is special in that its an android target that runs on host.
+    # You are allowed to depend on both android |deps_require_android| and
+    # non-android |deps_not_support_android| targets.
+    if not options.bypass_platform_checks and not options.is_robolectric:
       deps_require_android = (all_resources_deps +
           [d['name'] for d in all_library_deps if d['requires_android']])
       deps_not_support_android = (
@@ -1517,7 +1525,8 @@
     if options.res_sources_path:
       deps_info['res_sources_path'] = options.res_sources_path
 
-  if options.requires_android and options.type == 'java_library':
+  if (options.requires_android
+      and options.type == 'java_library') or options.is_robolectric:
     if options.package_name:
       deps_info['package_name'] = options.package_name
 
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 0b3fa446..b5eaa27 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -85,6 +85,8 @@
 _desugar_jdk_libs_json = "//third_party/r8/desugar_jdk_libs.json"
 _desugar_jdk_libs_jar = "//third_party/android_deps/libs/com_android_tools_desugar_jdk_libs/desugar_jdk_libs-1.1.5.jar"
 _desugar_jdk_libs_configuration_jar = "//third_party/android_deps/libs/com_android_tools_desugar_jdk_libs_configuration/desugar_jdk_libs_configuration-1.1.5.jar"
+_robolectric_jar_path =
+    "//third_party/robolectric/lib/android-all-12-robolectric-7732740.jar"
 
 # Put the bug number in the target name so that false-positives have a hint in
 # the error message about why non-existent dependencies are there.
@@ -288,6 +290,9 @@
         invoker.bypass_platform_checks) {
       args += [ "--bypass-platform-checks" ]
     }
+    if (defined(invoker.is_robolectric) && invoker.is_robolectric) {
+      args += [ "--is-robolectric" ]
+    }
 
     if (defined(invoker.apk_under_test)) {
       deps += [ "${invoker.apk_under_test}$build_config_target_suffix" ]
@@ -1404,6 +1409,11 @@
           invoker.tiered_stop_at_level_one) {
         args += [ "--tiered-stop-at-level-one" ]
       }
+      if (defined(invoker.extra_classpath_jars)) {
+        _rebased_extra_classpath_jars =
+            rebase_path(invoker.extra_classpath_jars, root_build_dir)
+        args += [ "--classpath=${_rebased_extra_classpath_jars}" ]
+      }
       if (defined(invoker.wrapper_script_args)) {
         args += [ "--" ] + invoker.wrapper_script_args
       }
@@ -1884,7 +1894,7 @@
       if (android_static_analysis == "build_server") {
         args += [ "--use-build-server" ]
       }
-      if (invoker.requires_android) {
+      if (invoker.include_android_sdk) {
         args += [ "--sdk-classpath-jars=@FileArg($_rebased_build_config:android:sdk_jars)" ]
       }
       if (invoker.is_prebuilt) {
@@ -3022,7 +3032,6 @@
         ]
       }
 
-      # Currently turbine does not support JDK11.
       if (invoker.supports_android || invoker.use_turbine) {
         args += [ "--java-version=1.8" ]
       }
@@ -3038,7 +3047,7 @@
       if (enable_kythe_annotations && !invoker.enable_errorprone) {
         args += [ "--enable-kythe-annotations" ]
       }
-      if (invoker.requires_android) {
+      if (invoker.include_android_sdk) {
         args += [ "--bootclasspath=@FileArg($_rebased_build_config:android:sdk_interface_jars)" ]
       }
       if (_chromium_code) {
@@ -3219,11 +3228,8 @@
   #    library via its built .jar rather than including its .java sources.
   #  proguard_enabled: Optional. True to enable ProGuard obfuscation.
   #  proguard_configs: Optional list of additional proguard config file paths.
-  #  bypass_platform_checks: Optional. If True, platform checks will not
-  #    be performed. They are used to verify that every target with
-  #    requires_android only depends on targets that, at least supports_android.
-  #    Similarly, if a target has !supports_android, then it cannot depend on
-  #    any other target that has requires_android.
+  #  is_robolectric: Optional. If True, this is a host side android test binary
+  #    which is allowed to depend on other android targets.
   #  include_java_resources: Optional. If True, include Java (not Android)
   #    resources into final .jar file.
   #  jar_excluded_patterns: Optional list of .class file patterns to exclude
@@ -3294,6 +3300,7 @@
         defined(invoker.requires_android) && invoker.requires_android
     _bypass_platform_checks = defined(invoker.bypass_platform_checks) &&
                               invoker.bypass_platform_checks
+    _is_robolectric = defined(invoker.is_robolectric) && invoker.is_robolectric
 
     _invoker_deps = []
     if (defined(invoker.deps)) {
@@ -3595,6 +3602,7 @@
 
       supports_android = _supports_android
       requires_android = _requires_android
+      is_robolectric = _is_robolectric
       bypass_platform_checks = _bypass_platform_checks
 
       if (defined(invoker.resources_package)) {
@@ -3649,10 +3657,12 @@
       }
 
       if (defined(invoker.resources_package) && _type == "java_library") {
-        assert(_requires_android || _bypass_platform_checks,
+        # TODO(crbug.com/1296632): remove _bypass_platform_checks from the list
+        # once all robolectric targets have migrated to robolectric_library.
+        assert(_requires_android || _bypass_platform_checks || _is_robolectric,
                "Setting resources_package applicable only for " +
-                   "android_library(), or java_library() with " +
-                   "bypass_platform_checks=true. Target=$target_name")
+                   "android_library(), or robolectric_library(). " +
+                   "Target=$target_name")
 
         # has _resources at the end so it looks like a resources pattern, since
         # it does act like one (and other resources patterns need to depend on
@@ -3707,7 +3717,7 @@
             }
             chromium_code = _chromium_code
             supports_android = _supports_android
-            requires_android = _requires_android
+            include_android_sdk = _is_robolectric || _requires_android
             if (!defined(deps)) {
               deps = []
             }
@@ -3841,7 +3851,8 @@
           forward_variables_from(invoker, [ "missing_classes_allowlist" ])
           deps = _unprocessed_jar_deps + _full_classpath_deps +
                  [ ":$_build_config_target_name" ]
-          requires_android = _requires_android
+
+          include_android_sdk = _requires_android || _is_robolectric
           target_label =
               get_label_info(":${invoker.target_name}", "label_no_toolchain")
           input_jar = _unprocessed_jar_path
@@ -3952,6 +3963,9 @@
           script_name = invoker.wrapper_script_name
         }
         deps = [ ":$_build_config_target_name" ]
+        if (_is_robolectric) {
+          extra_classpath_jars = [ _robolectric_jar_path ]
+        }
       }
       _public_deps += [ ":$_java_binary_script_target_name" ]
     }
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 4364e8f..b564825 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -1456,12 +1456,6 @@
       type = "junit_binary"
       main_target_name = invoker.target_name
 
-      # Include the android SDK jar(s) for resource processing.
-      include_android_sdk = true
-
-      # Robolectric can handle deps that set !supports_android as well those
-      # that set requires_android.
-      bypass_platform_checks = true
       deps = _invoker_deps
       testonly = true
       main_class = _main_class
@@ -1472,6 +1466,11 @@
       # 66%, which makes sharding more effective.
       tiered_stop_at_level_one = true
 
+      is_robolectric = true
+      include_android_sdk = true
+      alternative_android_sdk_dep =
+          "//third_party/robolectric:robolectric_test_sdk_java"
+
       if (!defined(srcjar_deps)) {
         srcjar_deps = []
       }
@@ -1995,6 +1994,70 @@
     }
   }
 
+  # Declare an Android robolectric library target
+  #
+  # This target creates an Android library containing java code and Android
+  # resources.
+  #
+  # Supports all variables of java_library(), plus:
+  #   deps: In addition to defining java deps, this can also include
+  #     android_assets() and android_resources() targets.
+  #   alternative_android_sdk_ijar: if set, the given android_sdk_ijar file
+  #     replaces the default android_sdk_ijar.
+  #   alternative_android_sdk_ijar_dep: the target that generates
+  #      alternative_android_sdk_ijar, must be set if alternative_android_sdk_ijar
+  #      is used.
+  #   alternative_android_sdk_jar: actual jar corresponding to
+  #      alternative_android_sdk_ijar, must be set if alternative_android_sdk_ijar
+  #      is used.
+  #
+  # Example
+  #   robolectric_library("foo_junit") {
+  #     sources = [
+  #       "android/org/chromium/foo/FooTest.java",
+  #       "android/org/chromium/foo/FooTestUtils.java",
+  #       "android/org/chromium/foo/FooMock.java",
+  #     ]
+  #     deps = [
+  #       "//base:base_junit_test_support"
+  #     ]
+  #     srcjar_deps = [
+  #       ":foo_generated_enum"
+  #     ]
+  #     jar_excluded_patterns = [
+  #       "*/FooService.class", "org/chromium/FooService\$*.class"
+  #     ]
+  #   }
+  template("robolectric_library") {
+    java_library(target_name) {
+      forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
+      forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
+
+      testonly = true
+
+      is_robolectric = true
+      include_android_sdk = true
+      alternative_android_sdk_dep =
+          "//third_party/robolectric:robolectric_test_sdk_java"
+
+      if (!defined(jar_excluded_patterns)) {
+        jar_excluded_patterns = []
+      }
+      jar_excluded_patterns += [
+        "*/R.class",
+        "*/R\$*.class",
+        "*/Manifest.class",
+        "*/Manifest\$*.class",
+        "*/GEN_JNI.class",
+      ]
+
+      if (!defined(deps)) {
+        deps = []
+      }
+      deps += [ "//third_party/android_deps:robolectric_all_java" ]
+    }
+  }
+
   # Declare an Android library target for a prebuilt jar
   #
   # This target creates an Android library containing java code and Android
diff --git a/build/config/android/test/classpath_order/BUILD.gn b/build/config/android/test/classpath_order/BUILD.gn
index decd1a84..af48416 100644
--- a/build/config/android/test/classpath_order/BUILD.gn
+++ b/build/config/android/test/classpath_order/BUILD.gn
@@ -92,8 +92,7 @@
   ]
 }
 
-java_library("junit_tests") {
-  bypass_platform_checks = true
+robolectric_library("junit_tests") {
   testonly = true
   sources =
       [ "java/src/org/chromium/build/classpath_order/ClassPathOrderTest.java" ]
diff --git a/chrome/VERSION b/chrome/VERSION
index 538ca9b..58f43f6 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=105
 MINOR=0
-BUILD=5119
+BUILD=5120
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 5bab68d8..66e1533 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1150,6 +1150,7 @@
     "//components/signin/public/android:java",
     "//components/signin/public/android:signin_java_test_support",
     "//components/sync/android:sync_java",
+    "//components/translate/content/android:junit",
     "//components/ukm/android:java",
     "//components/url_formatter/android:url_formatter_java",
     "//components/user_prefs/android:java",
@@ -1643,7 +1644,6 @@
     "//components/site_engagement/content/android:java",
     "//components/sync/android:sync_java",
     "//components/sync/protocol:protocol_java",
-    "//components/translate/content/android:javatests",
     "//components/url_formatter/android:url_formatter_java",
     "//components/user_prefs/android:java",
     "//components/version_info/android:version_constants_java",
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index 638a92ed..ebf5aa6 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -499,7 +499,6 @@
   "java/res/layout/contextual_search_card_icon_view.xml",
   "java/res/layout/contextual_search_context_view.xml",
   "java/res/layout/contextual_search_promo_view.xml",
-  "java/res/layout/contextual_search_promo_view_revised.xml",
   "java/res/layout/contextual_search_quick_action_icon_view.xml",
   "java/res/layout/contextual_search_related_searches_in_content_view.xml",
   "java/res/layout/contextual_search_related_searches_view.xml",
diff --git a/chrome/android/expectations/lint-suppressions.xml b/chrome/android/expectations/lint-suppressions.xml
index 5572d76f..5eb084f 100644
--- a/chrome/android/expectations/lint-suppressions.xml
+++ b/chrome/android/expectations/lint-suppressions.xml
@@ -287,6 +287,9 @@
     <!--TODO(crbug.com/1278431): Remove unused resources when UX is finalized. -->
     <ignore regexp="The resource `R.string.price_tracking_title` appears to be unused"/>
 
+    <!-- Temporarily suppressed until impelmentation is ready, see: https://crbug.com/1330631 -->
+    <ignore regexp="The resource `R.string.price_drop_spotted_iph` appears to be unused"/>
+
     <!-- Endnote: Please specify number of suppressions when adding more -->
   </issue>
   <issue id="VectorPath" severity="ignore"/>
diff --git a/chrome/android/features/android_library_factory/BUILD.gn b/chrome/android/features/android_library_factory/BUILD.gn
index cb40a2f..0044c32 100644
--- a/chrome/android/features/android_library_factory/BUILD.gn
+++ b/chrome/android/features/android_library_factory/BUILD.gn
@@ -69,8 +69,7 @@
   generator_deps = [ ":factory2" ]
 }
 
-java_library("junit_tests") {
-  bypass_platform_checks = true
+robolectric_library("junit_tests") {
   testonly = true
   sources = [ "junit/src/org/chromium/chrome/browser/android_library_factory/AndroidLibraryFactoryTest.java" ]
   deps = [
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java
index a9743e42..751478d 100644
--- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java
+++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java
@@ -16,7 +16,6 @@
 import static androidx.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE;
 import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA;
 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
 import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
 import static androidx.test.espresso.matcher.ViewMatchers.withParent;
@@ -1795,13 +1794,11 @@
 
     @Test
     @MediumTest
-    // clang-format off
-    @DisabledTest(message = "https://crbug.com/1144666")
-    @EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID,
-            ChromeFeatureList.TAB_TO_GTS_ANIMATION + "<Study"})
+    @DisabledTest(message = "https://crbug.com/1333098")
+    @EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID})
     public void testTabGroupManualSelection_DisabledForSingleTab() {
-        // clang-format on
         ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        TabSelectionEditorTestingRobot robot = new TabSelectionEditorTestingRobot();
         enterTabSwitcher(cta);
         verifyTabSwitcherCardCount(cta, 1);
 
@@ -1815,9 +1812,14 @@
         menuButton.getLocationOnScreen(location);
         UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
                 .click(location[0], location[1]);
-        onView(withText("Group tabs"))
+        // Even if we can tell the group option is disabled by looking at the device when the test
+        // is running, the espresso view matcher says it is enabled and all view parameters are the
+        // same with the one when we have two tabs. Thus, we check the item's click response here to
+        // tell if it is enabled.
+        onViewWaiting(withText("Group tabs"))
                 .inRoot(withDecorView(not(cta.getWindow().getDecorView())))
-                .check(matches(not(isEnabled())));
+                .perform(click());
+        robot.resultRobot.verifyTabSelectionEditorIsHidden();
 
         // Group option should be enabled when there is more than one single tab.
         createTabs(cta, false, 2);
@@ -1825,9 +1827,10 @@
         verifyTabSwitcherCardCount(cta, 2);
         UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
                 .click(location[0], location[1]);
-        onView(withText("Group tabs"))
+        onViewWaiting(withText("Group tabs"))
                 .inRoot(withDecorView(not(cta.getWindow().getDecorView())))
-                .check(matches(isEnabled()));
+                .perform(click());
+        robot.resultRobot.verifyTabSelectionEditorIsVisible();
     }
 
     @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 cb44b8c..40f83103 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
@@ -213,7 +213,6 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "crbug.com/1231024")
     public void testClickScrimCloseDialog() throws ExecutionException {
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         createTabs(cta, false, 2);
@@ -343,7 +342,6 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "crbug.com/1231024 and https://crbug.com/1121363")
     public void testUndoClosureInDialog_DialogUndoBar() throws ExecutionException {
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         createTabs(cta, false, 2);
@@ -464,7 +462,6 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "crbug.com/1206781")
     @Features.EnableFeatures(ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID)
     public void testSelectionEditorUngroup() throws ExecutionException {
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
index fbac6bc7..e727bee44 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -49,9 +49,6 @@
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.share.ShareDelegate;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabSelectionType;
-import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.top.Toolbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
@@ -297,19 +294,6 @@
         mWebFeedHasContent = false;
         mSectionHeaderIndex = 0;
 
-        TabModelObserver tabModelObserver = new TabModelObserver() {
-            @Override
-            public void didSelectTab(Tab tab, @TabSelectionType int type, int lastId) {
-                if (mReliabilityLogger != null) {
-                    mReliabilityLogger.onSwitchTabs();
-                }
-            }
-        };
-        tabModelSelector.getModel(/*incognito=*/false).addObserver(tabModelObserver);
-        // The feed isn't shown in incognito tabs, but we add the observer to record when the user
-        // switches to an incognito tab from the feed.
-        tabModelSelector.getModel(/*incognito=*/true).addObserver(tabModelObserver);
-
         Resources resources = mActivity.getResources();
 
         mRootView = new RootView(mActivity);
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java
index 23329a1b..8eb47da7 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java
@@ -81,13 +81,6 @@
                              "NtpFeedSurfaceLifecycleManager.saveInstanceState")) {
                     saveInstanceState();
                 }
-                FeedReliabilityLogger logger = coordinator.getReliabilityLogger();
-                if (logger != null) {
-                    try (TraceEvent e = TraceEvent.scoped(
-                                 "NtpFeedSurfaceLifecycleManager logger.onPageLoadStarted")) {
-                        logger.onPageLoadStarted();
-                    }
-                }
             }
         };
         mTab.addObserver(mTabObserver);
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedSurfaceCoordinatorIntegrationTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedSurfaceCoordinatorIntegrationTest.java
index 3ad1d135..b4e5d60 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedSurfaceCoordinatorIntegrationTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedSurfaceCoordinatorIntegrationTest.java
@@ -75,7 +75,7 @@
         mActivityTestRule.loadUrlInNewTab(UrlConstants.NTP_URL);
 
         // Make sure the eye icon starts off invisible, tab views enabled.
-        onView(withId(R.id.status_indicator)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.section_status_indicator)).check(matches(not(isDisplayed())));
         // We need to select the TabView which is a parent of the text view with "Following".
         onView(allOf(isFocusable(), withContentDescription("Following"),
                        hasDescendant(withText("Following"))))
@@ -86,7 +86,7 @@
         onView(withText("Turn off")).perform(ViewActions.click());
 
         // Verify that the eye icon appears, and the tab view disables.
-        onView(withId(R.id.status_indicator)).check(matches(isDisplayed()));
+        onView(withId(R.id.section_status_indicator)).check(matches(isDisplayed()));
         // Make sure the tab gets disabled.
         onView(allOf(isFocusable(), withContentDescription("Following"),
                        hasDescendant(withText("Following"))))
@@ -97,7 +97,7 @@
         onView(withText("Turn on")).perform(ViewActions.click());
 
         // Verify that the eye icon is gone, and the text is enabled.
-        onView(withId(R.id.status_indicator)).check(matches(not(isDisplayed())));
+        onView(withId(R.id.section_status_indicator)).check(matches(not(isDisplayed())));
         onView(allOf(isFocusable(), withContentDescription("Following"),
                        hasDescendant(withText("Following"))))
                 .check(matches(isEnabled()));
diff --git a/chrome/android/java/res/layout/contextual_search_promo_view.xml b/chrome/android/java/res/layout/contextual_search_promo_view.xml
index 0bf5075e..92354eae 100644
--- a/chrome/android/java/res/layout/contextual_search_promo_view.xml
+++ b/chrome/android/java/res/layout/contextual_search_promo_view.xml
@@ -1,9 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2016 The Chromium Authors. All rights reserved.
+<!-- Copyright 2021 The Chromium Authors. All rights reserved.
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/contextual_search_promo"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -20,11 +21,10 @@
 
         <RelativeLayout
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
+            android:layout_height="wrap_content">
 
-            <org.chromium.ui.widget.TextViewWithClickableSpans
-                android:id="@+id/contextual_search_promo_text"
+            <org.chromium.components.browser_ui.widget.text.TextViewWithCompoundDrawables
+                android:id="@+id/contextual_search_promo_title"
                 android:layout_alignParentTop="true"
                 android:layout_alignParentStart="true"
                 android:layout_alignParentEnd="true"
@@ -34,8 +34,28 @@
                 android:layout_marginStart="16dp"
                 android:layout_marginEnd="16dp"
                 android:bufferType="spannable"
+                android:drawableStart="@drawable/btn_info"
+                app:drawableWidth="24dp"
+                app:drawableHeight="24dp"
+                app:chromeDrawableTint="@macro/default_icon_color_accent1"
+                android:tintMode="src_in"
+                android:drawablePadding="8dp"
+                android:text="@string/contextual_search_promo_title"
                 android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
 
+            <org.chromium.ui.widget.TextViewWithClickableSpans
+                android:id="@+id/contextual_search_promo_text"
+                android:layout_below="@id/contextual_search_promo_title"
+                android:layout_alignParentStart="true"
+                android:layout_alignParentEnd="true"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="8dp"
+                android:layout_marginStart="48dp"
+                android:layout_marginEnd="16dp"
+                android:bufferType="spannable"
+                android:textAppearance="@style/TextAppearance.TextSmall.Secondary" />
+
             <org.chromium.ui.widget.ButtonCompat
                 android:id="@+id/contextual_search_allow_button"
                 android:layout_below="@id/contextual_search_promo_text"
@@ -46,7 +66,7 @@
                 android:layout_marginTop="16dp"
                 android:layout_marginBottom="16dp"
                 android:layout_marginEnd="16dp"
-                android:text="@string/contextual_search_allow_button"
+                android:text="@string/contextual_search_include_button"
                 style="@style/FilledButton.Flat" />
 
             <org.chromium.ui.widget.ButtonCompat
diff --git a/chrome/android/java/res/layout/contextual_search_promo_view_revised.xml b/chrome/android/java/res/layout/contextual_search_promo_view_revised.xml
deleted file mode 100644
index 92354eae..0000000
--- a/chrome/android/java/res/layout/contextual_search_promo_view_revised.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2021 The Chromium Authors. All rights reserved.
-     Use of this source code is governed by a BSD-style license that can be
-     found in the LICENSE file. -->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/contextual_search_promo"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:paddingTop="8dp"
-    android:paddingBottom="16dp"
-    android:paddingStart="16dp"
-    android:paddingEnd="16dp"
-    android:visibility="invisible">
-
-    <org.chromium.components.browser_ui.widget.MaterialCardViewNoShadow
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        style="@style/MaterialCardStyle">
-
-        <RelativeLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <org.chromium.components.browser_ui.widget.text.TextViewWithCompoundDrawables
-                android:id="@+id/contextual_search_promo_title"
-                android:layout_alignParentTop="true"
-                android:layout_alignParentStart="true"
-                android:layout_alignParentEnd="true"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="16dp"
-                android:layout_marginStart="16dp"
-                android:layout_marginEnd="16dp"
-                android:bufferType="spannable"
-                android:drawableStart="@drawable/btn_info"
-                app:drawableWidth="24dp"
-                app:drawableHeight="24dp"
-                app:chromeDrawableTint="@macro/default_icon_color_accent1"
-                android:tintMode="src_in"
-                android:drawablePadding="8dp"
-                android:text="@string/contextual_search_promo_title"
-                android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
-
-            <org.chromium.ui.widget.TextViewWithClickableSpans
-                android:id="@+id/contextual_search_promo_text"
-                android:layout_below="@id/contextual_search_promo_title"
-                android:layout_alignParentStart="true"
-                android:layout_alignParentEnd="true"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="8dp"
-                android:layout_marginStart="48dp"
-                android:layout_marginEnd="16dp"
-                android:bufferType="spannable"
-                android:textAppearance="@style/TextAppearance.TextSmall.Secondary" />
-
-            <org.chromium.ui.widget.ButtonCompat
-                android:id="@+id/contextual_search_allow_button"
-                android:layout_below="@id/contextual_search_promo_text"
-                android:layout_alignParentEnd="true"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="end"
-                android:layout_marginTop="16dp"
-                android:layout_marginBottom="16dp"
-                android:layout_marginEnd="16dp"
-                android:text="@string/contextual_search_include_button"
-                style="@style/FilledButton.Flat" />
-
-            <org.chromium.ui.widget.ButtonCompat
-                android:id="@+id/contextual_search_no_thanks_button"
-                android:layout_below="@id/contextual_search_promo_text"
-                android:layout_toStartOf="@id/contextual_search_allow_button"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="end"
-                android:layout_marginTop="16dp"
-                android:layout_marginBottom="16dp"
-                android:layout_marginEnd="16dp"
-                android:text="@string/contextual_search_no_thanks_button"
-                style="@style/TextButton" />
-        </RelativeLayout>
-    </org.chromium.components.browser_ui.widget.MaterialCardViewNoShadow>
-</FrameLayout>
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
index e3fda0af..9691c9f2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -1044,12 +1044,7 @@
                 public void onPromoOptIn() {}
 
                 @Override
-                public void onPromoOptOut() {
-                    if (!ChromeFeatureList.isEnabled(
-                                ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)) {
-                        closePanel(OverlayPanel.StateChangeReason.OPTOUT, true);
-                    }
-                }
+                public void onPromoOptOut() {}
             };
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java
index 79d7841c..3cf8660 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchPreferenceFragment;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchUma;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.layouts.animation.CompositorAnimator;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.components.browser_ui.settings.SettingsLauncher;
@@ -84,11 +83,8 @@
      */
     ContextualSearchPromoControl(OverlayPanel panel, ContextualSearchPromoHost host,
             Context context, ViewGroup container, DynamicResourceLoader resourceLoader) {
-        super(panel,
-                ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
-                        ? R.layout.contextual_search_promo_view_revised
-                        : R.layout.contextual_search_promo_view,
-                R.id.contextual_search_promo, context, container, resourceLoader);
+        super(panel, R.layout.contextual_search_promo_view, R.id.contextual_search_promo, context,
+                container, resourceLoader);
 
         mDpToPx = context.getResources().getDisplayMetrics().density;
         mBackgroundColor =
@@ -333,11 +329,7 @@
                 (View ignored) -> ContextualSearchPromoControl.this.handleClickSettingsLink());
 
         promoText.setText(SpanApplier.applySpans(
-                view.getResources().getString(
-                        ChromeFeatureList.isEnabled(
-                                ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
-                                ? R.string.contextual_search_promo_description
-                                : R.string.contextual_search_short_description),
+                view.getResources().getString(R.string.contextual_search_promo_description),
                 new SpanApplier.SpanInfo("<link>", "</link>", settingsLink)));
         promoText.setMovementMethod(LinkMovementMethod.getInstance());
 
@@ -418,9 +410,7 @@
 
         ContextualSearchManager.onPromoShown();
 
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)) {
-            updatePromoHeight();
-        }
+        updatePromoHeight();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
index 358f6c8..2eae8479 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -41,9 +41,6 @@
     static final String RELATED_SEARCHES_DEFAULT_QUERY_CHIP_MAX_WIDTH_SP_PARAM_NAME =
             "default_query_max_width_sp";
 
-    static final String CONTEXTUAL_SEARCH_PROMO_CARD_MAX_SHOWN_PARAM_NAME = "promo_card_max_shown";
-    private static final int PROMO_DEFAULT_LIMIT = 3;
-
     // Cached values to avoid repeated and redundant JNI operations.
     private static Boolean sEnabled;
     private static Boolean[] sSwitches = new Boolean[ContextualSearchSwitch.NUM_ENTRIES];
@@ -308,13 +305,6 @@
                 RELATED_SEARCHES_DEFAULT_QUERY_CHIP_MAX_WIDTH_SP_PARAM_NAME, 0);
     }
 
-    /* Return the max times to show the promo card. */
-    static int getDefaultPromoCardShownTimes() {
-        return ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
-                ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS,
-                CONTEXTUAL_SEARCH_PROMO_CARD_MAX_SHOWN_PARAM_NAME, PROMO_DEFAULT_LIMIT);
-    }
-
     // --------------------------------------------------------------------------------------------
     // Helpers.
     // --------------------------------------------------------------------------------------------
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
index 1462535..5340fb22 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -1846,7 +1846,7 @@
      * @param enabled Whether The user to choose fully Contextual Search privacy opt-in.
      */
     public static void setContextualSearchPromoCardSelection(boolean enabled) {
-        ContextualSearchPolicy.setContextualSearchPromoCardSelection(enabled);
+        ContextualSearchPolicy.setContextualSearchFullyOptedIn(enabled);
     }
 
     /** Notifies that a promo card has been shown. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
index ea73ad8..514a44e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -43,6 +43,7 @@
     private static final String PATH_AMP = "/amp/";
     private static final int REMAINING_NOT_APPLICABLE = -1;
     private static final int TAP_TRIGGERED_PROMO_LIMIT = 50;
+    private static final int PROMO_DEFAULT_LIMIT = 3;
 
     // Constants related to the Contextual Search preference.
     private static final String CONTEXTUAL_SEARCH_DISABLED = "false";
@@ -180,13 +181,8 @@
      * @return Whether the Opt-out promo is available to be shown in any panel.
      */
     boolean isPromoAvailable() {
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)) {
-            // Only show promo card a limited number of times.
-            return isUserUndecided()
-                    && getContextualSearchPromoCardShownCount()
-                    < ContextualSearchFieldTrial.getDefaultPromoCardShownTimes();
-        }
-        return isUserUndecided();
+        // Only show promo card a limited number of times.
+        return isUserUndecided() && getContextualSearchPromoCardShownCount() < PROMO_DEFAULT_LIMIT;
     }
 
     /**
@@ -402,34 +398,15 @@
     }
 
     /**
-     * Sets the contextual search states based on the user's selection in the promo card.
-     * If the the feature CONTEXTUAL_SEARCH_NEW_SETTINGS enabled,
-     * @See {@link #setContextualSearchFullyOptedIn(boolean)}.
-     * If the the feature CONTEXTUAL_SEARCH_NEW_SETTINGS is not enabled,
-     * @See {@link #setContextualSearchState(boolean)}.
-     * @param enabled Whether The user to choose fully Contextual Search privacy opt-in.
-     */
-    static void setContextualSearchPromoCardSelection(boolean enabled) {
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)) {
-            setContextualSearchFullyOptedIn(enabled);
-        } else {
-            setContextualSearchState(enabled);
-        }
-    }
-
-    /**
-     * Explicitly sets whether Contextual Search states.
-     * 'enabled' is true - fully opt in.
-     * 'enabled' is false - the feature is disabled.
+     * Explicitly set whether Contextual Search is enabled or not, with the enabled state being
+     * either fully or default-enabled based on previous state. 'enabled' is true - fully opt in or
+     * default-enabled based on previous state. 'enabled' is false - the feature is disabled.
      * @param enabled Whether Contextual Search should be enabled.
      */
     static void setContextualSearchState(boolean enabled) {
         @ContextualSearchPreference
-        int onState = ContextualSearchPreference.ENABLED;
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)) {
-            onState = isContextualSearchOptInEnabled() ? ContextualSearchPreference.ENABLED
+        int onState = isContextualSearchOptInEnabled() ? ContextualSearchPreference.ENABLED
                                                        : ContextualSearchPreference.UNINITIALIZED;
-        }
         setContextualSearchStateInternal(enabled ? onState : ContextualSearchPreference.DISABLED);
     }
 
@@ -438,11 +415,8 @@
      *         itself.
      */
     static boolean isContextualSearchPrefFullyOptedIn() {
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
-                && !isContextualSearchOptInUninitialized()) {
-            return isContextualSearchOptInEnabled();
-        }
-        return isContextualSearchEnabled();
+        return isContextualSearchOptInUninitialized() ? isContextualSearchEnabled()
+                                                      : isContextualSearchOptInEnabled();
     }
 
     /**
@@ -459,19 +433,10 @@
 
     /** Notifies that a promo card has been shown. */
     static void onPromoShown() {
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)) {
-            int count = getContextualSearchPromoCardShownCount();
-            count++;
-            setContextualSearchPromoCardShownCount(count);
-            ContextualSearchUma.logRevisedPromoOpenCount(count);
-        }
-    }
-
-    /**
-     * @return Whether the Contextual Search Multilevel settings UI should be shown.
-     */
-    static boolean shouldShowMultilevelSettingsUI() {
-        return ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS);
+        int count = getContextualSearchPromoCardShownCount();
+        count++;
+        setContextualSearchPromoCardShownCount(count);
+        ContextualSearchUma.logRevisedPromoOpenCount(count);
     }
 
     /**
@@ -555,11 +520,7 @@
     boolean isUserUndecided() {
         if (mDidOverrideFullyEnabledForTesting) return !mFullyEnabledForTesting;
 
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)) {
-            return isContextualSearchUninitialized() && isContextualSearchOptInUninitialized();
-        }
-
-        return isContextualSearchUninitialized();
+        return isContextualSearchUninitialized() && isContextualSearchOptInUninitialized();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPreferenceFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPreferenceFragment.java
index 5b0c9b6..5c93422 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPreferenceFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPreferenceFragment.java
@@ -12,7 +12,6 @@
 import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
-import org.chromium.components.browser_ui.settings.TextMessagePreference;
 
 /**
  * Fragment to manage the Contextual Search preference in Chrome Settings, and to explain to the
@@ -21,7 +20,6 @@
 public class ContextualSearchPreferenceFragment extends PreferenceFragmentCompat {
     static final String PREF_CONTEXTUAL_SEARCH_SWITCH = "contextual_search_switch";
     static final String PREF_WAS_FULLY_ENABLED_SWITCH = "see_better_results_switch";
-    static final String PREF_CONTEXTUAL_SEARCH_DESCRIPTION = "contextual_search_description";
 
     @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
@@ -43,8 +41,7 @@
         contextualSearchSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
             ContextualSearchPolicy.setContextualSearchState((boolean) newValue);
             ContextualSearchUma.logMainPreferenceChange((boolean) newValue);
-            seeBetterResultsSwitch.setVisible(
-                    ContextualSearchPolicy.shouldShowMultilevelSettingsUI() && (boolean) newValue);
+            seeBetterResultsSwitch.setVisible((boolean) newValue);
             return true;
         });
 
@@ -60,13 +57,6 @@
             return true;
         });
 
-        seeBetterResultsSwitch.setVisible(ContextualSearchPolicy.shouldShowMultilevelSettingsUI()
-                && isContextualSearchEnabled);
-
-        if (ContextualSearchPolicy.shouldShowMultilevelSettingsUI()) {
-            TextMessagePreference contextualSearchDescription =
-                    (TextMessagePreference) findPreference(PREF_CONTEXTUAL_SEARCH_DESCRIPTION);
-            contextualSearchDescription.setTitle(R.string.contextual_search_description_revised);
-        }
+        seeBetterResultsSwitch.setVisible(isContextualSearchEnabled);
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicyTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicyTest.java
index cf5023b..6a8d5628 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicyTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicyTest.java
@@ -23,7 +23,6 @@
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -32,8 +31,6 @@
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
-import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
-import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.search_engines.TemplateUrl;
 import org.chromium.components.user_prefs.UserPrefs;
@@ -175,37 +172,10 @@
     @Test
     @SmallTest
     @Feature({"ContextualSearch"})
-    @DisableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
-    public void testIsUserUndecided_NoMultilevelSettingsUI_Disable() {
+    public void testIsUserUndecided_Disable() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             Assert.assertTrue(mPolicy.isUserUndecided());
-            ContextualSearchPolicy.setContextualSearchPromoCardSelection(false);
-            Assert.assertFalse(mPolicy.isUserUndecided());
-            Assert.assertTrue(ContextualSearchPolicy.isContextualSearchDisabled());
-        });
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"ContextualSearch"})
-    @DisableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
-    public void testIsUserUndecided_NoMultilevelSettingsUI_Enable() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertTrue(mPolicy.isUserUndecided());
-            ContextualSearchPolicy.setContextualSearchPromoCardSelection(true);
-            Assert.assertFalse(mPolicy.isUserUndecided());
-            Assert.assertTrue(ContextualSearchPolicy.isContextualSearchEnabled());
-        });
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"ContextualSearch"})
-    @EnableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
-    public void testIsUserUndecided_MultilevelSettingsUI_Disable() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertTrue(mPolicy.isUserUndecided());
-            ContextualSearchPolicy.setContextualSearchPromoCardSelection(false);
+            ContextualSearchPolicy.setContextualSearchFullyOptedIn(false);
             Assert.assertFalse(mPolicy.isUserUndecided());
             Assert.assertTrue(ContextualSearchPolicy.isContextualSearchUninitialized());
         });
@@ -214,11 +184,10 @@
     @Test
     @SmallTest
     @Feature({"ContextualSearch"})
-    @EnableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
-    public void testIsUserUndecided_MultilevelSettingsUI_Enable() {
+    public void testIsUserUndecided_Enable() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             Assert.assertTrue(mPolicy.isUserUndecided());
-            ContextualSearchPolicy.setContextualSearchPromoCardSelection(true);
+            ContextualSearchPolicy.setContextualSearchFullyOptedIn(true);
             Assert.assertFalse(mPolicy.isUserUndecided());
             Assert.assertTrue(ContextualSearchPolicy.isContextualSearchEnabled());
         });
@@ -227,7 +196,6 @@
     @Test
     @SmallTest
     @Feature({"ContextualSearch"})
-    @EnableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
     public void testIsPromoAvailable() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             Assert.assertTrue(mPolicy.isPromoAvailable());
@@ -249,18 +217,17 @@
     @Test
     @SmallTest
     @Feature({"ContextualSearch"})
-    @DisableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
-    public void testIsContextualSearchFullyOptedIn_NoMultilevelSettingsUI() {
+    public void testIsContextualSearchFullyOptedIn() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             // Default is not fully opted in.
             Assert.assertFalse(ContextualSearchPolicy.isContextualSearchPrefFullyOptedIn());
 
             // Choose not to opt in.
-            ContextualSearchPolicy.setContextualSearchPromoCardSelection(false);
+            ContextualSearchPolicy.setContextualSearchFullyOptedIn(false);
             Assert.assertFalse(ContextualSearchPolicy.isContextualSearchPrefFullyOptedIn());
 
             // Choose to opt in.
-            ContextualSearchPolicy.setContextualSearchPromoCardSelection(true);
+            ContextualSearchPolicy.setContextualSearchFullyOptedIn(true);
             Assert.assertTrue(ContextualSearchPolicy.isContextualSearchPrefFullyOptedIn());
         });
     }
@@ -268,26 +235,6 @@
     @Test
     @SmallTest
     @Feature({"ContextualSearch"})
-    @EnableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
-    public void testIsContextualSearchFullyOptedIn_MultilevelSettingsUI() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            // Default is not fully opted in.
-            Assert.assertFalse(ContextualSearchPolicy.isContextualSearchPrefFullyOptedIn());
-
-            // Choose not to opt in.
-            ContextualSearchPolicy.setContextualSearchPromoCardSelection(false);
-            Assert.assertFalse(ContextualSearchPolicy.isContextualSearchPrefFullyOptedIn());
-
-            // Choose to opt in.
-            ContextualSearchPolicy.setContextualSearchPromoCardSelection(true);
-            Assert.assertTrue(ContextualSearchPolicy.isContextualSearchPrefFullyOptedIn());
-        });
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"ContextualSearch"})
-    @EnableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
     public void testSetContextualSearchFullyOptedIn() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             // Default is not fully opted in.
@@ -313,12 +260,11 @@
     @Test
     @SmallTest
     @Feature({"ContextualSearch"})
-    @EnableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
     public void testShouldPreviousGestureResolve() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             Assert.assertFalse(mPolicy.shouldPreviousGestureResolve());
 
-            ContextualSearchPolicy.setContextualSearchPromoCardSelection(true);
+            ContextualSearchPolicy.setContextualSearchFullyOptedIn(true);
             Assert.assertTrue(mPolicy.shouldPreviousGestureResolve());
 
             ContextualSearchPolicy.setContextualSearchFullyOptedIn(false);
@@ -329,12 +275,11 @@
     @Test
     @SmallTest
     @Feature({"ContextualSearch"})
-    @EnableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
     public void testIsContextualSearchFullyEnabled() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             Assert.assertFalse(mPolicy.isContextualSearchFullyEnabled());
 
-            ContextualSearchPolicy.setContextualSearchPromoCardSelection(true);
+            ContextualSearchPolicy.setContextualSearchFullyOptedIn(true);
             Assert.assertTrue(mPolicy.isContextualSearchFullyEnabled());
 
             ContextualSearchPolicy.setContextualSearchFullyOptedIn(false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPreferenceFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPreferenceFragmentTest.java
index 8fdde3e..19a0f8a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPreferenceFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPreferenceFragmentTest.java
@@ -14,13 +14,10 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.UiThreadTest;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
-import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.user_prefs.UserPrefs;
@@ -84,23 +81,6 @@
     @Test
     @UiThreadTest
     @SmallTest
-    @DisableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
-    public void testSeeBetterResultsSwitch_NoShowWhenDisabled() {
-        // "See Better Results" Switch is not shown since the feature is disabled.
-        Assert.assertFalse(
-                "See Better Results Switch should not be shown when the feature is disabled",
-                mSeeBetterResultsSwitchPreference.isVisible());
-
-        mContextualSearchSwitchPreference.performClick();
-        Assert.assertFalse(
-                "See Better Results Switch should not be shown when the feature is disabled",
-                mSeeBetterResultsSwitchPreference.isVisible());
-    }
-
-    @Test
-    @UiThreadTest
-    @SmallTest
-    @EnableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
     public void testSeeBetterResultsSwitch() {
         // "See Better Results" Switch is visible when Contextual Search Switch is on.
         Assert.assertTrue("The Contextual Search default value for the switch should be on.",
@@ -128,7 +108,6 @@
     @Test
     @UiThreadTest
     @SmallTest
-    @EnableFeatures(ChromeFeatureList.CONTEXTUAL_SEARCH_NEW_SETTINGS)
     public void testSeeBetterResultsSwitch_SavePreviousOptInStatus() {
         // "See Better Results" Switch is visible when Contextual Search Switch is on.
         Assert.assertTrue("The Contextual Search default value for the switch should be on.",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorTest.java
index 63fc2684..d6d21c9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorTest.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.status_indicator;
 
 import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
 import static androidx.test.espresso.assertion.ViewAssertions.matches;
 import static androidx.test.espresso.matcher.ViewMatchers.Visibility.GONE;
 import static androidx.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE;
@@ -201,13 +202,14 @@
     @CommandLineFlags.Add({"enable-features=" + ChromeFeatureList.START_SURFACE_ANDROID + "<Study",
             "force-fieldtrials=Study/Group",
             "force-fieldtrial-params=Study.Group:start_surface_variation/single"})
-    @DisabledTest(message = "https://crbug.com/1109965")
     public void testShowAndHideOnStartSurface() {
         // clang-format on
         TabUiTestHelper.enterTabSwitcher(mActivityTestRule.getActivity());
 
         onView(withId(R.id.secondary_tasks_surface_view)).check(matches(isDisplayed()));
-        onView(withId(R.id.status_indicator)).check(matches(withEffectiveVisibility(GONE)));
+        // R.id.status_indicator won't be in the View tree until the indicator is shown for the
+        // first time and the corresponding ViewStub is inflated.
+        onView(withId(R.id.status_indicator)).check(doesNotExist());
         onView(withId(R.id.control_container)).check(matches(withTopMargin(0)));
         Assert.assertFalse("Wrong initial composited view visibility.",
                 mStatusIndicatorSceneLayer.isSceneOverlayTreeShowing());
@@ -243,10 +245,6 @@
 
         TestThreadUtils.runOnUiThreadBlocking(() -> mStatusIndicatorCoordinator.hide());
 
-        CriteriaHelper.pollUiThread(() -> {
-            Criteria.checkThat(getStatusIndicator(), Matchers.is(Matchers.nullValue()));
-        });
-
         onView(withId(R.id.status_indicator)).check(matches(withEffectiveVisibility(GONE)));
         onView(withId(R.id.control_container)).check(matches(withTopMargin(0)));
         onView(withId(R.id.secondary_tasks_surface_view))
@@ -256,7 +254,6 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1109965")
     public void testShowAndHideOnNTP() {
         mActivityTestRule.loadUrl(UrlConstants.NTP_URL);
         Tab tab = mActivityTestRule.getActivity().getActivityTab();
@@ -265,7 +262,9 @@
         final View view = tab.getNativePage().getView();
         view.setId(viewId);
 
-        onView(withId(R.id.status_indicator)).check(matches(withEffectiveVisibility(GONE)));
+        // R.id.status_indicator won't be in the View tree until the indicator is shown for the
+        // first time and the corresponding ViewStub is inflated.
+        onView(withId(R.id.status_indicator)).check(doesNotExist());
         onView(withId(R.id.control_container)).check(matches(withTopMargin(0)));
         onView(withId(viewId)).check(matches(withTopMargin(0)));
         Assert.assertFalse("Wrong initial composited view visibility.",
@@ -299,13 +298,14 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1109965")
     public void testShowAndHideOnRecentTabsPage() {
         mActivityTestRule.loadUrl(UrlConstants.RECENT_TABS_URL);
         final Tab tab = mActivityTestRule.getActivity().getActivityTab();
         RecentTabsPageTestUtils.waitForRecentTabsPageLoaded(tab);
 
-        onView(withId(R.id.status_indicator)).check(matches(withEffectiveVisibility(GONE)));
+        // R.id.status_indicator won't be in the View tree until the indicator is shown for the
+        // first time and the corresponding ViewStub is inflated.
+        onView(withId(R.id.status_indicator)).check(doesNotExist());
         onView(withId(R.id.control_container)).check(matches(withTopMargin(0)));
         onView(withId(R.id.recent_tabs_root))
                 .check(matches(
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java
index 8a79a3f..1298177 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java
@@ -437,24 +437,6 @@
                 .logUiStarting(SURFACE_TYPE, SURFACE_CREATION_TIME_NS);
     }
 
-    @Test
-    public void testLogSwitchTabs() {
-        when(mLaunchReliabilityLogger.isLaunchInProgress()).thenReturn(true);
-        mTabModel.selectTab();
-        verify(mLaunchReliabilityLogger, times(1))
-                .logLaunchFinished(
-                        anyLong(), eq(DiscoverLaunchResult.NAVIGATED_TO_ANOTHER_TAB.getNumber()));
-    }
-
-    @Test
-    public void testLogSwitchTabsIncognito() {
-        when(mLaunchReliabilityLogger.isLaunchInProgress()).thenReturn(true);
-        mTabModelIncognito.selectTab();
-        verify(mLaunchReliabilityLogger, times(1))
-                .logLaunchFinished(
-                        anyLong(), eq(DiscoverLaunchResult.NAVIGATED_TO_ANOTHER_TAB.getNumber()));
-    }
-
     private boolean hasStreamBound() {
         if (mCoordinator.getMediatorForTesting().getCurrentStreamForTesting() == null) {
             return false;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManagerTest.java
index 0a153db..990b820d 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManagerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManagerTest.java
@@ -303,11 +303,4 @@
         ApplicationStatus.onStateChangeForTesting(mActivity, ActivityState.PAUSED);
         verify(mCoordinator).onActivityPaused();
     }
-
-    @Test
-    @SmallTest
-    public void testLogPageLoadStarted() {
-        mNtpStreamLifecycleManager.getTabObserverForTesting().onPageLoadStarted(null, null);
-        verify(mFeedReliabilityLogger, times(1)).onPageLoadStarted();
-    }
 }
diff --git a/chrome/android/webapk/test/BUILD.gn b/chrome/android/webapk/test/BUILD.gn
index 90d04418..015cc74 100644
--- a/chrome/android/webapk/test/BUILD.gn
+++ b/chrome/android/webapk/test/BUILD.gn
@@ -4,9 +4,7 @@
 
 import("//build/config/android/rules.gni")
 
-java_library("junit_test_support") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit_test_support") {
   testonly = true
   sources = [ "src/org/chromium/webapk/test/WebApkTestHelper.java" ]
   deps = [
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 96663fb..0d2d8e2b 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -2573,6 +2573,10 @@
                desc="Label for the button prompting to open a download while deep scanning is in progress">
         Open Now
       </message>
+      <message name="IDS_DOWNLOAD_BUBBLE_REVIEW"
+               desc="Label for the button prompting the dialog containing the enterprise administrator's message explaining the violation.">
+        Review
+      </message>
       <message name="IDS_DOWNLOAD_BUBBLE_INTERRUPTED_STATUS_DISK_FULL"
                desc="Status text for a download item that was interrupted because there is not enough room on the disk to download this file.">
         Out of storage space
@@ -3756,6 +3760,9 @@
         <message name="IDS_CERT_EXTENSION_NON_CRITICAL" desc="The text displayed in the certificate details dialog for a given extension which is not critical">
           Not Critical
         </message>
+        <message name="IDS_CERT_DUMP_ERROR" desc="The text displayed in the certificate viewer dialog for a given field which could not be decoded">
+          Error: Unable to decode certificate
+        </message>
         <message name="IDS_CERT_EXTENSION_DUMP_ERROR" desc="The text displayed in the certificate details dialog for a given extension which could not be decoded">
           Error: Unable to decode extension
         </message>
diff --git a/chrome/app/generated_resources_grd/IDS_CERT_DUMP_ERROR.png.sha1 b/chrome/app/generated_resources_grd/IDS_CERT_DUMP_ERROR.png.sha1
new file mode 100644
index 0000000..78da3b84
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_CERT_DUMP_ERROR.png.sha1
@@ -0,0 +1 @@
+93bc3903698ab1e98b05471d98eb715aa314e7df
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_DOWNLOAD_BUBBLE_REVIEW.png.sha1 b/chrome/app/generated_resources_grd/IDS_DOWNLOAD_BUBBLE_REVIEW.png.sha1
new file mode 100644
index 0000000..18f18c6
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_DOWNLOAD_BUBBLE_REVIEW.png.sha1
@@ -0,0 +1 @@
+f1e9524d1231bc8eeb4f71af29ea1a1d419907ed
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 0cd85f9..31f4dd7c 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -512,16 +512,6 @@
     "external_protocol/external_protocol_observer.h",
     "fast_checkout/fast_checkout_features.cc",
     "fast_checkout/fast_checkout_features.h",
-    "favicon/chrome_favicon_client.cc",
-    "favicon/chrome_favicon_client.h",
-    "favicon/favicon_service_factory.cc",
-    "favicon/favicon_service_factory.h",
-    "favicon/favicon_utils.cc",
-    "favicon/favicon_utils.h",
-    "favicon/history_ui_favicon_request_handler_factory.cc",
-    "favicon/history_ui_favicon_request_handler_factory.h",
-    "favicon/large_icon_service_factory.cc",
-    "favicon/large_icon_service_factory.h",
     "feature_engagement/tracker_factory.cc",
     "feature_engagement/tracker_factory.h",
     "feature_guide/notifications/feature_notification_guide_service_factory.cc",
@@ -1891,6 +1881,7 @@
 
   allow_circular_includes_from = [
     "//chrome/browser/devtools",
+    "//chrome/browser/favicon",
     "//chrome/browser/profiling_host",
     "//chrome/browser/ui",
     "//chrome/browser/ui/webui/bluetooth_internals",
@@ -1959,6 +1950,7 @@
     "//chrome/browser/breadcrumbs",
     "//chrome/browser/browsing_data:constants",
     "//chrome/browser/devtools",
+    "//chrome/browser/favicon",
     "//chrome/browser/feature_guide/notifications:public",
     "//chrome/browser/feature_guide/notifications/internal",
     "//chrome/browser/first_party_sets",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 2b04217..6a0f5ec 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1856,17 +1856,6 @@
     {"Dense Title Right", kExploreSitesDenseTitleRight,
      std::size(kExploreSitesDenseTitleRight), nullptr}};
 
-const FeatureEntry::FeatureParam kContextualSearchPromoCardShow3Times = {
-    "promo_card_max_shown", "3"};
-const FeatureEntry::FeatureParam kContextualSearchPromoCardShow100Times = {
-    "promo_card_max_shown", "100"};
-const FeatureEntry::FeatureVariation ContextualSearchNewSettingsVariations[] = {
-    {"with promo show 3 times", &kContextualSearchPromoCardShow3Times, 1,
-     nullptr},
-    {"with promo show 100 times", &kContextualSearchPromoCardShow100Times, 1,
-     nullptr},
-};
-
 const FeatureEntry::FeatureParam kRelatedSearchesUrl = {"stamp", "1Ru"};
 const FeatureEntry::FeatureParam kRelatedSearchesContent = {"stamp", "1Rc"};
 const FeatureEntry::FeatureVariation kRelatedSearchesVariations[] = {
@@ -3317,13 +3306,6 @@
      flag_descriptions::kContextualSearchForceCaptionName,
      flag_descriptions::kContextualSearchForceCaptionDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kContextualSearchForceCaption)},
-    {"contextual-search-new-settings",
-     flag_descriptions::KContextualSearchNewSettingsName,
-     flag_descriptions::KContextualSearchNewSettingsDescription, kOsAndroid,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(
-         chrome::android::KContextualSearchNewSettings,
-         ContextualSearchNewSettingsVariations,
-         "ContextualSearchNewSettings")},
     {"contextual-search-translations",
      flag_descriptions::kContextualSearchTranslationsName,
      flag_descriptions::kContextualSearchTranslationsDescription, kOsAndroid,
@@ -8779,6 +8761,16 @@
      FEATURE_VALUE_TYPE(commerce::kCommerceHintAndroid)},
 #endif
 
+    {"autofill-enable-get-details-for-enroll-parsing-in-upload-card-response",
+     flag_descriptions::
+         kAutofillEnableGetDetailsForEnrollParsingInUploadCardResponseName,
+     flag_descriptions::
+         kAutofillEnableGetDetailsForEnrollParsingInUploadCardResponseDescription,
+     kOsAll,
+     FEATURE_VALUE_TYPE(
+         autofill::features::
+             kAutofillEnableGetDetailsForEnrollParsingInUploadCardResponse)},
+
     // 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/intents/BUILD.gn b/chrome/browser/android/browserservices/intents/BUILD.gn
index d51bea76..e177d14f 100644
--- a/chrome/browser/android/browserservices/intents/BUILD.gn
+++ b/chrome/browser/android/browserservices/intents/BUILD.gn
@@ -33,9 +33,7 @@
   ]
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/chrome/browser/browserservices/intents/WebApkInfoTest.java",
diff --git a/chrome/browser/android/browserservices/verification/BUILD.gn b/chrome/browser/android/browserservices/verification/BUILD.gn
index 519d90c..d2bcb48a 100644
--- a/chrome/browser/android/browserservices/verification/BUILD.gn
+++ b/chrome/browser/android/browserservices/verification/BUILD.gn
@@ -40,8 +40,8 @@
 android_library("javatests") {
   testonly = true
   sources = [
-    "./java/src/org/chromium/chrome/browser/browserservices/verification/OriginVerifierTest.java",
-    "./java/src/org/chromium/chrome/browser/browserservices/verification/PackageFingerprintCalculatorTest.java",
+    "java/src/org/chromium/chrome/browser/browserservices/verification/OriginVerifierTest.java",
+    "java/src/org/chromium/chrome/browser/browserservices/verification/PackageFingerprintCalculatorTest.java",
   ]
 
   deps = [
@@ -60,11 +60,9 @@
   ]
 }
 
-java_library("junit_test_support") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit_test_support") {
   testonly = true
-  sources = [ "./java/src/org/chromium/chrome/browser/browserservices/verification/OriginVerifierUnitTestSupport.java" ]
+  sources = [ "java/src/org/chromium/chrome/browser/browserservices/verification/OriginVerifierUnitTestSupport.java" ]
   deps = [
     ":java",
     "//components/embedder_support/android:util_java",
diff --git a/chrome/browser/android/webapps/launchpad/BUILD.gn b/chrome/browser/android/webapps/launchpad/BUILD.gn
index c2375da..ee3ffe8 100644
--- a/chrome/browser/android/webapps/launchpad/BUILD.gn
+++ b/chrome/browser/android/webapps/launchpad/BUILD.gn
@@ -69,9 +69,7 @@
   ]
 }
 
-android_library("junit_tests") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("junit_tests") {
   testonly = true
 
   sources = [
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 494bb43..6cd709b 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -1814,7 +1814,8 @@
   // a profile for app controller, so `_lastProfile` will be nullptr.
   if (_lastProfile) {
     Browser* browser = chrome::FindBrowserWithProfile(_lastProfile);
-    _lastActiveColorProvider = browser->window()->GetColorProvider();
+    if (browser && browser->window())
+      _lastActiveColorProvider = browser->window()->GetColorProvider();
   }
 }
 
diff --git a/chrome/browser/apps/app_discovery_service/game_fetcher.cc b/chrome/browser/apps/app_discovery_service/game_fetcher.cc
index a6c2f8c..701b84c 100644
--- a/chrome/browser/apps/app_discovery_service/game_fetcher.cc
+++ b/chrome/browser/apps/app_discovery_service/game_fetcher.cc
@@ -189,9 +189,9 @@
     if (localised_name.empty()) {
       continue;
     }
-    results.push_back(Result(AppSource::kGames,
-                             app_with_locale.app().app_id_for_platform(),
-                             localised_name, std::move(extras)));
+    results.emplace_back(AppSource::kGames,
+                         app_with_locale.app().app_id_for_platform(),
+                         localised_name, std::move(extras));
   }
   return results;
 }
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc
index 9effcea..f057322 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc
@@ -269,6 +269,8 @@
 }
 
 gfx::ImageSkia ApplyBackgroundAndMask(const gfx::ImageSkia& image) {
+  if (image.isNull())
+    return gfx::ImageSkia();
   return gfx::ImageSkiaOperations::CreateButtonBackground(
       SK_ColorWHITE, image, LoadMaskImage(GetScaleToSize(image)));
 }
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_factory_unittest.cc b/chrome/browser/apps/app_service/app_icon/app_icon_factory_unittest.cc
index acceb68..07a53c61 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_factory_unittest.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_factory_unittest.cc
@@ -1078,4 +1078,10 @@
   }
 }
 
+// Regression test for crash. https://crbug.com/1335266
+TEST_F(WebAppIconFactoryTest, ApplyBackgroundAndMask_NullImage) {
+  gfx::ImageSkia image = apps::ApplyBackgroundAndMask(gfx::ImageSkia());
+  DCHECK(image.isNull());
+}
+
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_source.cc b/chrome/browser/apps/app_service/app_icon/app_icon_source.cc
index c09319e..c0012c0 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_source.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_source.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_features.h"
 #include "chrome/common/url_constants.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
@@ -96,21 +95,11 @@
   auto* app_service_proxy =
       apps::AppServiceProxyFactory::GetForProfile(profile_);
   const std::string app_id = path_parts[0];
-  const auto app_type =
-      app_service_proxy->AppRegistryCache().GetAppType(app_id);
-  constexpr bool allow_placeholder_icon = false;
-  if (base::FeatureList::IsEnabled(features::kAppServiceLoadIconWithoutMojom)) {
-    app_service_proxy->LoadIcon(
-        app_type, app_id, IconType::kCompressed, size_in_dip,
-        allow_placeholder_icon,
-        base::BindOnce(&RunCallback, std::move(callback)));
-  } else {
-    app_service_proxy->LoadIcon(
-        ConvertAppTypeToMojomAppType(app_type), app_id,
-        apps::mojom::IconType::kCompressed, size_in_dip, allow_placeholder_icon,
-        MojomIconValueToIconValueCallback(
-            base::BindOnce(&RunCallback, std::move(callback))));
-  }
+  app_service_proxy->LoadIcon(
+      app_service_proxy->AppRegistryCache().GetAppType(app_id), app_id,
+      IconType::kCompressed, size_in_dip,
+      /*allow_placeholder_icon=*/false,
+      base::BindOnce(&RunCallback, std::move(callback)));
 }
 
 std::string AppIconSource::GetMimeType(const std::string&) {
diff --git a/chrome/browser/apps/app_service/app_icon/arc_icon_once_loader.cc b/chrome/browser/apps/app_service/app_icon/arc_icon_once_loader.cc
index edc8298..cb7a4b8d 100644
--- a/chrome/browser/apps/app_service/app_icon/arc_icon_once_loader.cc
+++ b/chrome/browser/apps/app_service/app_icon/arc_icon_once_loader.cc
@@ -168,8 +168,7 @@
   OnIconUpdated(icon);
 }
 
-ArcIconOnceLoader::ArcIconOnceLoader(Profile* profile)
-    : profile_(profile), stop_observing_called_(false) {
+ArcIconOnceLoader::ArcIconOnceLoader(Profile* profile) : profile_(profile) {
   ArcAppListPrefs::Get(profile)->AddObserver(this);
   arc_app_icon_factory_ = std::make_unique<arc::ArcAppIconFactory>();
 }
diff --git a/chrome/browser/apps/app_service/app_icon/arc_icon_once_loader.h b/chrome/browser/apps/app_service/app_icon/arc_icon_once_loader.h
index 997c142..ca2c8f4 100644
--- a/chrome/browser/apps/app_service/app_icon/arc_icon_once_loader.h
+++ b/chrome/browser/apps/app_service/app_icon/arc_icon_once_loader.h
@@ -88,7 +88,7 @@
   void MaybeLoadPendingIconRequest();
 
   Profile* const profile_;
-  bool stop_observing_called_;
+  bool stop_observing_called_ = false;
   std::map<SizeAndType, std::unique_ptr<SizeSpecificLoader>>
       size_specific_loaders_;
 
diff --git a/chrome/browser/apps/app_service/app_icon/icon_key_util.cc b/chrome/browser/apps/app_service/app_icon/icon_key_util.cc
index 1b231521..b1b027e8 100644
--- a/chrome/browser/apps/app_service/app_icon/icon_key_util.cc
+++ b/chrome/browser/apps/app_service/app_icon/icon_key_util.cc
@@ -6,7 +6,7 @@
 
 namespace apps_util {
 
-IncrementingIconKeyFactory::IncrementingIconKeyFactory() : last_timeline_(0) {}
+IncrementingIconKeyFactory::IncrementingIconKeyFactory() = default;
 
 apps::mojom::IconKeyPtr IncrementingIconKeyFactory::MakeIconKey(
     uint32_t icon_effects) {
diff --git a/chrome/browser/apps/app_service/app_icon/icon_key_util.h b/chrome/browser/apps/app_service/app_icon/icon_key_util.h
index 2018f92..010da8ecf 100644
--- a/chrome/browser/apps/app_service/app_icon/icon_key_util.h
+++ b/chrome/browser/apps/app_service/app_icon/icon_key_util.h
@@ -37,7 +37,7 @@
   std::unique_ptr<apps::IconKey> CreateIconKey(uint32_t icon_effects);
 
  private:
-  uint64_t last_timeline_;
+  uint64_t last_timeline_ = 0;
 };
 
 }  // namespace apps_util
diff --git a/chrome/browser/apps/app_service/app_service_proxy_ash.cc b/chrome/browser/apps/app_service/app_service_proxy_ash.cc
index 460488e..c9a5a40 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_ash.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_ash.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/supervised_user/grit/supervised_user_unscaled_resources.h"
 #include "chrome/browser/web_applications/app_service/web_apps.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
-#include "chrome/common/chrome_features.h"
 #include "components/account_id/account_id.h"
 #include "components/app_constants/constants.h"
 #include "components/app_restore/full_restore_save_handler.h"
@@ -476,7 +475,6 @@
   auto icon_key = update.IconKey();
   constexpr bool kAllowPlaceholderIcon = false;
   constexpr int32_t kIconSize = 48;
-  auto app_type = update.AppType();
   auto icon_type = IconType::kStandard;
 
   // For browser tests, load the app icon, because there is no family link
@@ -485,27 +483,13 @@
   // For non_child profile, load the app icon, because the app is blocked by
   // admin.
   if (!dialog_created_callback_.is_null() || !profile_->IsChild()) {
-    if (base::FeatureList::IsEnabled(
-            features::kAppServiceLoadIconWithoutMojom)) {
-      if (!icon_key.has_value()) {
-        std::move(callback).Run(std::make_unique<IconValue>());
-        return;
-      }
-      LoadIconFromIconKey(app_type, update.AppId(), icon_key.value(), icon_type,
-                          kIconSize, kAllowPlaceholderIcon,
-                          std::move(callback));
-    } else {
-      if (!icon_key.has_value()) {
-        MojomIconValueToIconValueCallback(std::move(callback))
-            .Run(apps::mojom::IconValue::New());
-        return;
-      }
-      LoadIconFromIconKey(
-          ConvertAppTypeToMojomAppType(app_type), update.AppId(),
-          ConvertIconKeyToMojomIconKey(icon_key.value()),
-          apps::mojom::IconType::kStandard, kIconSize, kAllowPlaceholderIcon,
-          MojomIconValueToIconValueCallback(std::move(callback)));
+    if (!icon_key.has_value()) {
+      std::move(callback).Run(std::make_unique<IconValue>());
+      return;
     }
+    LoadIconFromIconKey(update.AppType(), update.AppId(), icon_key.value(),
+                        icon_type, kIconSize, kAllowPlaceholderIcon,
+                        std::move(callback));
     return;
   }
 
diff --git a/chrome/browser/apps/app_service/app_service_proxy_lacros.cc b/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
index 9b3058b4..4d8fa325 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_lacros.cc
@@ -441,7 +441,7 @@
 
 AppServiceProxyLacros::InnerIconLoader::InnerIconLoader(
     AppServiceProxyLacros* host)
-    : host_(host), overriding_icon_loader_for_testing_(nullptr) {}
+    : host_(host) {}
 
 absl::optional<IconKey> AppServiceProxyLacros::InnerIconLoader::GetIconKey(
     const std::string& app_id) {
diff --git a/chrome/browser/apps/app_service/app_service_proxy_lacros.h b/chrome/browser/apps/app_service/app_service_proxy_lacros.h
index ffa8646..1e2cf82 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_lacros.h
+++ b/chrome/browser/apps/app_service/app_service_proxy_lacros.h
@@ -320,7 +320,7 @@
     // field.
     AppServiceProxyLacros* host_;
 
-    apps::IconLoader* overriding_icon_loader_for_testing_;
+    apps::IconLoader* overriding_icon_loader_for_testing_ = nullptr;
   };
 
   bool IsValidProfile();
diff --git a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
index 97dfaac..57f3c18 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
@@ -31,12 +31,6 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image_skia_rep.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chrome/common/chrome_features.h"
-#endif
-
-// TODO(crbug.com/1253250):  Remove mojom related test cases.
-
 namespace apps {
 
 class AppServiceProxyTest : public testing::Test {
@@ -77,21 +71,6 @@
       return nullptr;
     }
 
-    std::unique_ptr<Releaser> LoadIconFromIconKey(
-        apps::mojom::AppType app_type,
-        const std::string& app_id,
-        apps::mojom::IconKeyPtr icon_key,
-        apps::mojom::IconType icon_type,
-        int32_t size_hint_in_dip,
-        bool allow_placeholder_icon,
-        apps::mojom::Publisher::LoadIconCallback callback) override {
-      if (icon_type == apps::mojom::IconType::kUncompressed) {
-        pending_callbacks_.push_back(
-            IconValueToMojomIconValueCallback(std::move(callback)));
-      }
-      return nullptr;
-    }
-
     int num_inner_finished_callbacks_ = 0;
     std::vector<apps::LoadIconCallback> pending_callbacks_;
   };
@@ -108,38 +87,19 @@
   content::BrowserTaskEnvironment task_environment_;
 };
 
-class AppServiceProxyIconTest : public AppServiceProxyTest,
-                                public ::testing::WithParamInterface<bool> {
+class AppServiceProxyIconTest : public AppServiceProxyTest {
  protected:
-  bool IsLoadIconWithoutMojomEnabled() const { return GetParam(); }
-
   UniqueReleaser LoadIcon(apps::IconLoader* loader, const std::string& app_id) {
-    static constexpr int32_t size_hint_in_dip = 1;
-    static bool allow_placeholder_icon = false;
-
-    if (IsLoadIconWithoutMojomEnabled()) {
-      static constexpr auto app_type = AppType::kWeb;
-      static constexpr auto icon_type = IconType::kUncompressed;
-      return loader->LoadIcon(
-          app_type, app_id, icon_type, size_hint_in_dip, allow_placeholder_icon,
-          base::BindOnce([](int* num_callbacks,
-                            apps::IconValuePtr icon) { ++(*num_callbacks); },
-                         &num_outer_finished_callbacks_));
-    } else {
-      static constexpr auto app_type = apps::mojom::AppType::kWeb;
-      static constexpr auto icon_type = apps::mojom::IconType::kUncompressed;
-      return loader->LoadIcon(
-          app_type, app_id, icon_type, size_hint_in_dip, allow_placeholder_icon,
-          base::BindOnce(
-              [](int* num_callbacks, apps::mojom::IconValuePtr icon) {
-                ++(*num_callbacks);
-              },
-              &num_outer_finished_callbacks_));
-    }
+    return loader->LoadIcon(
+        AppType::kWeb, app_id, IconType::kUncompressed, /*size_hint_in_dip=*/1,
+        /*allow_placeholder_icon=*/false,
+        base::BindOnce([](int* num_callbacks,
+                          apps::IconValuePtr icon) { ++(*num_callbacks); },
+                       &num_outer_finished_callbacks_));
   }
 };
 
-TEST_P(AppServiceProxyIconTest, IconCache) {
+TEST_F(AppServiceProxyIconTest, IconCache) {
   // This is mostly a sanity check. For an isolated, comprehensive unit test of
   // the IconCache code, see icon_cache_unittest.cc.
   //
@@ -185,7 +145,7 @@
   EXPECT_EQ(3, NumOuterFinishedCallbacks());
 }
 
-TEST_P(AppServiceProxyIconTest, IconCoalescer) {
+TEST_F(AppServiceProxyIconTest, IconCoalescer) {
   // This is mostly a sanity check. For an isolated, comprehensive unit test of
   // the IconCoalescer code, see icon_coalescer_unittest.cc.
   //
@@ -291,12 +251,6 @@
 #endif
 }
 
-// The parameter indicates whether the kAppServiceLoadIconWithoutMojom feature
-// is enabled.
-INSTANTIATE_TEST_SUITE_P(All,
-                         AppServiceProxyIconTest,
-                         ::testing::Values(true, false));
-
 #if !BUILDFLAG(IS_CHROMEOS_LACROS)
 class AppServiceProxyPreferredAppsTest : public AppServiceProxyTest {
  public:
@@ -528,59 +482,75 @@
   bool called_1 = false;
   bool called_2 = false;
   auto instance_id_1 = base::UnguessableToken::Create();
-  LaunchResult result_1;
-  result_1.instance_ids.push_back(instance_id_1);
   auto instance_id_2 = base::UnguessableToken::Create();
-  LaunchResult result_2;
-  result_2.instance_ids.push_back(instance_id_2);
 
   // If the instance is not created yet, the callback will be stored.
-  proxy.OnLaunched(
-      base::BindOnce([](bool* called,
-                        apps::LaunchResult&& launch_result) { *called = true; },
-                     &called_1),
-      std::move(result_1));
+  {
+    LaunchResult result_1;
+    result_1.instance_ids.push_back(instance_id_1);
+    proxy.OnLaunched(base::BindOnce(
+                         [](bool* called, apps::LaunchResult&& launch_result) {
+                           *called = true;
+                         },
+                         &called_1),
+                     std::move(result_1));
+  }
   EXPECT_EQ(proxy.callback_list_.size(), 1U);
   EXPECT_FALSE(called_1);
 
-  proxy.OnLaunched(
-      base::BindOnce([](bool* called,
-                        apps::LaunchResult&& launch_result) { *called = true; },
-                     &called_2),
-      std::move(result_2));
+  {
+    LaunchResult result_2;
+    result_2.instance_ids.push_back(instance_id_2);
+    proxy.OnLaunched(base::BindOnce(
+                         [](bool* called, apps::LaunchResult&& launch_result) {
+                           *called = true;
+                         },
+                         &called_2),
+                     std::move(result_2));
+  }
   EXPECT_EQ(proxy.callback_list_.size(), 2U);
   EXPECT_FALSE(called_2);
 
   // Once the instance is created, the callback will be called.
-  auto delta = std::make_unique<apps::Instance>("abc", instance_id_1, nullptr);
-  proxy.InstanceRegistry().OnInstance(std::move(delta));
+  {
+    auto delta =
+        std::make_unique<apps::Instance>("abc", instance_id_1, nullptr);
+    proxy.InstanceRegistry().OnInstance(std::move(delta));
+  }
   EXPECT_EQ(proxy.callback_list_.size(), 1U);
   EXPECT_TRUE(called_1);
   EXPECT_FALSE(called_2);
 
   // New callback with existing instance will be called immediately.
   called_1 = false;
-  proxy.OnLaunched(
-      base::BindOnce([](bool* called,
-                        apps::LaunchResult&& launch_result) { *called = true; },
-                     &called_1),
-      std::move(result_1));
+  {
+    LaunchResult result_3;
+    proxy.OnLaunched(base::BindOnce(
+                         [](bool* called, apps::LaunchResult&& launch_result) {
+                           *called = true;
+                         },
+                         &called_1),
+                     std::move(result_3));
+  }
   EXPECT_EQ(proxy.callback_list_.size(), 1U);
   EXPECT_TRUE(called_1);
   EXPECT_FALSE(called_2);
 
   // A launch that results in multiple instances.
-  LaunchResult result_multi;
   auto instance_id_3 = base::UnguessableToken::Create();
   auto instance_id_4 = base::UnguessableToken::Create();
-  result_multi.instance_ids.push_back(instance_id_3);
-  result_multi.instance_ids.push_back(instance_id_4);
   bool called_multi = false;
-  proxy.OnLaunched(
-      base::BindOnce([](bool* called,
-                        apps::LaunchResult&& launch_result) { *called = true; },
-                     &called_multi),
-      std::move(result_multi));
+  {
+    LaunchResult result_multi;
+    result_multi.instance_ids.push_back(instance_id_3);
+    result_multi.instance_ids.push_back(instance_id_4);
+    proxy.OnLaunched(base::BindOnce(
+                         [](bool* called, apps::LaunchResult&& launch_result) {
+                           *called = true;
+                         },
+                         &called_multi),
+                     std::move(result_multi));
+  }
   EXPECT_EQ(proxy.callback_list_.size(), 2U);
   EXPECT_FALSE(called_multi);
   proxy.InstanceRegistry().OnInstance(
diff --git a/chrome/browser/apps/app_service/app_service_test.cc b/chrome/browser/apps/app_service/app_service_test.cc
index 284273b1..1b36bd0 100644
--- a/chrome/browser/apps/app_service/app_service_test.cc
+++ b/chrome/browser/apps/app_service/app_service_test.cc
@@ -7,7 +7,6 @@
 #include "base/run_loop.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/common/chrome_features.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
 #include "ui/gfx/image/image_unittest_util.h"
@@ -66,34 +65,18 @@
     int32_t size_hint_in_dip) {
   gfx::ImageSkia image_skia;
   base::RunLoop run_loop;
-  base::OnceClosure load_app_icon_callback = run_loop.QuitClosure();
 
-  if (base::FeatureList::IsEnabled(features::kAppServiceLoadIconWithoutMojom)) {
-    app_service_proxy_->LoadIcon(
-        ConvertMojomAppTypToAppType(app_type), app_id, IconType::kStandard,
-        size_hint_in_dip, false /* allow_placeholder_icon */,
-        base::BindOnce(
-            [](gfx::ImageSkia* icon, base::OnceClosure load_app_icon_callback,
-               IconValuePtr icon_value) {
-              DCHECK_EQ(IconType::kStandard, icon_value->icon_type);
-              *icon = icon_value->uncompressed;
-              std::move(load_app_icon_callback).Run();
-            },
-            &image_skia, std::move(load_app_icon_callback)));
-  } else {
-    app_service_proxy_->LoadIcon(
-        app_type, app_id, apps::mojom::IconType::kStandard, size_hint_in_dip,
-        false /* allow_placeholder_icon */,
-        base::BindOnce(
-            [](gfx::ImageSkia* icon, base::OnceClosure load_app_icon_callback,
-               apps::mojom::IconValuePtr icon_value) {
-              DCHECK_EQ(apps::mojom::IconType::kStandard,
-                        icon_value->icon_type);
-              *icon = icon_value->uncompressed;
-              std::move(load_app_icon_callback).Run();
-            },
-            &image_skia, std::move(load_app_icon_callback)));
-  }
+  app_service_proxy_->LoadIcon(
+      ConvertMojomAppTypToAppType(app_type), app_id, IconType::kStandard,
+      size_hint_in_dip, false /* allow_placeholder_icon */,
+      base::BindOnce(
+          [](gfx::ImageSkia* icon, base::OnceClosure load_app_icon_callback,
+             IconValuePtr icon_value) {
+            DCHECK_EQ(IconType::kStandard, icon_value->icon_type);
+            *icon = icon_value->uncompressed;
+            std::move(load_app_icon_callback).Run();
+          },
+          &image_skia, run_loop.QuitClosure()));
   run_loop.Run();
   return image_skia;
 }
diff --git a/chrome/browser/apps/app_service/instance_registry_updater.cc b/chrome/browser/apps/app_service/instance_registry_updater.cc
index c4a37a0..ae20ad8f 100644
--- a/chrome/browser/apps/app_service/instance_registry_updater.cc
+++ b/chrome/browser/apps/app_service/instance_registry_updater.cc
@@ -35,7 +35,7 @@
       &browser_app_instance_registry_);
 }
 
-InstanceRegistryUpdater::~InstanceRegistryUpdater() {}
+InstanceRegistryUpdater::~InstanceRegistryUpdater() = default;
 
 void InstanceRegistryUpdater::OnBrowserWindowAdded(
     const BrowserWindowInstance& instance) {
diff --git a/chrome/browser/apps/app_service/intent_util.cc b/chrome/browser/apps/app_service/intent_util.cc
index ed6cc9c..399bac9f 100644
--- a/chrome/browser/apps/app_service/intent_util.cc
+++ b/chrome/browser/apps/app_service/intent_util.cc
@@ -789,8 +789,8 @@
         break;
       case apps::mojom::ConditionType::kHost:
         for (auto& condition_value : condition->condition_values) {
-          authorities.push_back(arc::IntentFilter::AuthorityEntry(
-              /*host=*/condition_value->value, /*port=*/0));
+          authorities.emplace_back(
+              /*host=*/condition_value->value, /*port=*/0);
         }
         break;
       case apps::mojom::ConditionType::kPattern:
@@ -814,8 +814,7 @@
               NOTREACHED();
               return arc::IntentFilter();
           }
-          paths.push_back(arc::IntentFilter::PatternMatcher(
-              condition_value->value, match_type));
+          paths.emplace_back(condition_value->value, match_type);
         }
         break;
       case apps::mojom::ConditionType::kAction:
diff --git a/chrome/browser/apps/app_service/intent_util_browsertest.cc b/chrome/browser/apps/app_service/intent_util_browsertest.cc
index 8a41e32..8dc623f9 100644
--- a/chrome/browser/apps/app_service/intent_util_browsertest.cc
+++ b/chrome/browser/apps/app_service/intent_util_browsertest.cc
@@ -125,11 +125,7 @@
 
 }  // namespace
 
-class WebAppsUtilsBrowserTest : public InProcessBrowserTest {
- public:
-  WebAppsUtilsBrowserTest() {}
-  ~WebAppsUtilsBrowserTest() override = default;
-};
+using WebAppsUtilsBrowserTest = InProcessBrowserTest;
 
 IN_PROC_BROWSER_TEST_F(WebAppsUtilsBrowserTest, CreateIntentFilters) {
   ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chrome/browser/apps/app_service/launch_utils_unittest.cc b/chrome/browser/apps/app_service/launch_utils_unittest.cc
index 3fffd298..57c52b2 100644
--- a/chrome/browser/apps/app_service/launch_utils_unittest.cc
+++ b/chrome/browser/apps/app_service/launch_utils_unittest.cc
@@ -241,7 +241,7 @@
   auto container = apps::mojom::LaunchContainer::kLaunchContainerWindow;
   auto disposition = WindowOpenDisposition::NEW_WINDOW;
   auto params = CreateLaunchParams(container, disposition, false);
-  params.launch_files.push_back(base::FilePath("root"));
+  params.launch_files.emplace_back("root");
 
   auto crosapi_params = apps::ConvertLaunchParamsToCrosapi(params, &profile_);
   auto converted_params =
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc
index 3f7d5efc..ca3ea385 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc
@@ -395,19 +395,19 @@
   void VerifyMetrics() {
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(AppTypeName::kArc),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kArc, apps::InstallReason::kUser),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             AppTypeName::kBuiltIn),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kBuiltIn, apps::InstallReason::kSystem),
-        /*expected_count=*/1);
+        /*count=*/1);
 
     // Should be 3 Borealis apps: The installer/launcher created by the
     // BorealisApps class, plus the two created in this test.
@@ -416,102 +416,102 @@
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             AppTypeName::kBorealis),
         /*sample=*/borealis_apps_count,
-        /*bucket_count=*/1);
+        /*expected_bucket_count=*/1);
 
     // The installer/launcher is preinstalled, the others are user-installed.
     histogram_tester_.ExpectUniqueSample(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kBorealis, apps::InstallReason::kDefault),
         /*sample=*/1,
-        /*bucket_count=*/1);
+        /*expected_bucket_count=*/1);
     histogram_tester_.ExpectUniqueSample(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kBorealis, apps::InstallReason::kUser),
         /*sample=*/borealis_apps_count - 1,
-        /*bucket_count=*/1);
+        /*expected_bucket_count=*/1);
 
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             AppTypeName::kCrostini),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kCrostini, apps::InstallReason::kUser),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             AppTypeName::kChromeApp),
-        /*expected_count=*/0);
+        /*count=*/0);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             GetWebAppTypeName()),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             GetWebAppTypeName(), apps::InstallReason::kSync),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             AppTypeName::kMacOs),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kMacOs, apps::InstallReason::kUnknown),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             AppTypeName::kPluginVm),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kPluginVm, apps::InstallReason::kUser),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             AppTypeName::kStandaloneBrowser),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kStandaloneBrowser, apps::InstallReason::kSystem),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             AppTypeName::kStandaloneBrowserChromeApp),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kStandaloneBrowserChromeApp,
             apps::InstallReason::kUser),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             AppTypeName::kStandaloneBrowserChromeApp),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kStandaloneBrowserChromeApp,
             apps::InstallReason::kUser),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             AppTypeName::kRemote),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kRemote, apps::InstallReason::kPolicy),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountHistogramNameForTest(
             AppTypeName::kSystemWeb),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             AppTypeName::kSystemWeb, apps::InstallReason::kSystem),
-        /*expected_count=*/1);
+        /*count=*/1);
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsCountPerInstallReasonHistogramNameForTest(
             GetWebAppTypeName(), apps::InstallReason::kSubApp),
-        /*expected_count=*/1);
+        /*count=*/1);
   }
 
   void ModifyInstance(const std::string& app_id,
@@ -607,30 +607,32 @@
     EXPECT_EQ(time_delta, unreported_duration.value());
   }
 
-  void VerifyAppRunningDurationCountHistogram(base::HistogramBase::Count count,
-                                              AppTypeName app_type_name) {
+  void VerifyAppRunningDurationCountHistogram(
+      base::HistogramBase::Count expected_count,
+      AppTypeName app_type_name) {
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsRunningDurationHistogramNameForTest(
             app_type_name),
-        count);
+        expected_count);
   }
 
-  void VerifyAppRunningDurationHistogram(base::TimeDelta time_delta,
-                                         base::HistogramBase::Count count,
-                                         AppTypeName app_type_name) {
+  void VerifyAppRunningDurationHistogram(
+      base::TimeDelta time_delta,
+      base::HistogramBase::Count expected_count,
+      AppTypeName app_type_name) {
     histogram_tester().ExpectTimeBucketCount(
         AppPlatformMetrics::GetAppsRunningDurationHistogramNameForTest(
             app_type_name),
-        time_delta, count);
+        time_delta, expected_count);
   }
 
   void VerifyAppRunningPercentageCountHistogram(
-      base::HistogramBase::Count count,
+      base::HistogramBase::Count expected_count,
       AppTypeName app_type_name) {
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsRunningPercentageHistogramNameForTest(
             app_type_name),
-        count);
+        expected_count);
   }
 
   void VerifyAppRunningPercentageHistogram(
@@ -643,26 +645,27 @@
         count, expected_count);
   }
 
-  void VerifyAppActivatedCount(int count, AppTypeName app_type_name) {
+  void VerifyAppActivatedCount(int expected_count, AppTypeName app_type_name) {
     DictionaryPrefUpdate update(GetPrefService(), kAppActivatedCount);
     std::string key = GetAppTypeHistogramName(app_type_name);
 
     absl::optional<int> activated_count = update->FindIntPath(key);
-    if (count == 0) {
+    if (expected_count == 0) {
       EXPECT_FALSE(activated_count.has_value());
       return;
     }
 
     ASSERT_TRUE(activated_count.has_value());
-    EXPECT_EQ(count, activated_count.value());
+    EXPECT_EQ(expected_count, activated_count.value());
   }
 
-  void VerifyAppActivatedCountHistogram(base::HistogramBase::Count count,
-                                        AppTypeName app_type_name) {
+  void VerifyAppActivatedCountHistogram(
+      base::HistogramBase::Count expected_count,
+      AppTypeName app_type_name) {
     histogram_tester().ExpectTotalCount(
         AppPlatformMetrics::GetAppsActivatedCountHistogramNameForTest(
             app_type_name),
-        count);
+        expected_count);
   }
 
   void VerifyAppActivatedHistogram(int count,
@@ -674,34 +677,36 @@
         count, expected_count);
   }
 
-  void VerifyAppUsageTimeCountHistogram(base::HistogramBase::Count count,
-                                        AppTypeName app_type_name) {
+  void VerifyAppUsageTimeCountHistogram(
+      base::HistogramBase::Count expected_count,
+      AppTypeName app_type_name) {
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsUsageTimeHistogramNameForTest(app_type_name),
-        count);
+        expected_count);
   }
 
-  void VerifyAppUsageTimeCountHistogram(base::HistogramBase::Count count,
-                                        AppTypeNameV2 app_type_name) {
+  void VerifyAppUsageTimeCountHistogram(
+      base::HistogramBase::Count expected_count,
+      AppTypeNameV2 app_type_name) {
     histogram_tester_.ExpectTotalCount(
         AppPlatformMetrics::GetAppsUsageTimeHistogramNameForTest(app_type_name),
-        count);
+        expected_count);
   }
 
   void VerifyAppUsageTimeHistogram(base::TimeDelta time_delta,
-                                   base::HistogramBase::Count count,
+                                   base::HistogramBase::Count expected_count,
                                    AppTypeName app_type_name) {
     histogram_tester().ExpectTimeBucketCount(
         AppPlatformMetrics::GetAppsUsageTimeHistogramNameForTest(app_type_name),
-        time_delta, count);
+        time_delta, expected_count);
   }
 
   void VerifyAppUsageTimeHistogram(base::TimeDelta time_delta,
-                                   base::HistogramBase::Count count,
+                                   base::HistogramBase::Count expected_count,
                                    AppTypeNameV2 app_type_name) {
     histogram_tester().ExpectTimeBucketCount(
         AppPlatformMetrics::GetAppsUsageTimeHistogramNameForTest(app_type_name),
-        time_delta, count);
+        time_delta, expected_count);
   }
 
   void VerifyAppUsageTimeUkmWithUkmName(const std::string& ukm_name,
@@ -912,7 +917,7 @@
   task_environment_.FastForwardBy(base::Hours(1));
   histogram_tester().ExpectTotalCount(
       AppPlatformMetrics::GetAppsCountHistogramNameForTest(AppTypeName::kArc),
-      /*expected_count=*/0);
+      /*count=*/0);
   EXPECT_EQ(AppPlatformMetricsService::GetDayIdForTesting(base::Time::Now()),
             GetDayIdPref());
 }
@@ -938,7 +943,7 @@
   task_environment_.FastForwardBy(base::Days(1));
   histogram_tester().ExpectTotalCount(
       AppPlatformMetrics::GetAppsCountHistogramNameForTest(AppTypeName::kArc),
-      /*expected_count=*/2);
+      /*count=*/2);
 }
 
 TEST_P(AppPlatformMetricsServiceTest, BrowserWindow) {
diff --git a/chrome/browser/apps/app_service/metrics/browser_to_tab_list.cc b/chrome/browser/apps/app_service/metrics/browser_to_tab_list.cc
index 3640626..8bfd55d 100644
--- a/chrome/browser/apps/app_service/metrics/browser_to_tab_list.cc
+++ b/chrome/browser/apps/app_service/metrics/browser_to_tab_list.cc
@@ -59,8 +59,7 @@
   }
 
   if (!found) {
-    active_browsers_to_tabs_.push_back(
-        BrowserToTab(browser_window, tab_id, app_id));
+    active_browsers_to_tabs_.emplace_back(browser_window, tab_id, app_id);
   }
 }
 
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.cc b/chrome/browser/apps/app_service/metrics/website_metrics.cc
index 612bb07..bfa245f 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics.cc
+++ b/chrome/browser/apps/app_service/metrics/website_metrics.cc
@@ -69,7 +69,7 @@
   ActiveTabWebContentsObserver& operator=(const ActiveTabWebContentsObserver&) =
       delete;
 
-  ~ActiveTabWebContentsObserver() override {}
+  ~ActiveTabWebContentsObserver() override = default;
 
   // content::WebContentsObserver
   void PrimaryPageChanged(content::Page& page) override {
diff --git a/chrome/browser/apps/app_service/publishers/crostini_apps.cc b/chrome/browser/apps/app_service/publishers/crostini_apps.cc
index f058085..a696959 100644
--- a/chrome/browser/apps/app_service/publishers/crostini_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/crostini_apps.cc
@@ -61,7 +61,7 @@
 namespace apps {
 
 CrostiniApps::CrostiniApps(AppServiceProxy* proxy)
-    : AppPublisher(proxy), profile_(proxy->profile()), registry_(nullptr) {}
+    : AppPublisher(proxy), profile_(proxy->profile()) {}
 
 CrostiniApps::~CrostiniApps() {
   if (registry_) {
diff --git a/chrome/browser/apps/app_service/publishers/crostini_apps.h b/chrome/browser/apps/app_service/publishers/crostini_apps.h
index 7cda7c86..a5c44db 100644
--- a/chrome/browser/apps/app_service/publishers/crostini_apps.h
+++ b/chrome/browser/apps/app_service/publishers/crostini_apps.h
@@ -113,7 +113,7 @@
 
   Profile* const profile_;
 
-  guest_os::GuestOsRegistryService* registry_;
+  guest_os::GuestOsRegistryService* registry_ = nullptr;
 
   apps_util::IncrementingIconKeyFactory icon_key_factory_;
 
diff --git a/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc b/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc
index 02e43ef4..763189c 100644
--- a/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc
@@ -164,7 +164,7 @@
 namespace apps {
 
 PluginVmApps::PluginVmApps(AppServiceProxy* proxy)
-    : AppPublisher(proxy), profile_(proxy->profile()), registry_(nullptr) {
+    : AppPublisher(proxy), profile_(proxy->profile()) {
   // Don't show anything for non-primary profiles. We can't use
   // `PluginVmFeatures::Get()->IsAllowed()` here because we still let the user
   // uninstall Plugin VM when it isn't allowed for some other reasons (e.g.
diff --git a/chrome/browser/apps/app_service/publishers/plugin_vm_apps.h b/chrome/browser/apps/app_service/publishers/plugin_vm_apps.h
index 9133dad..b98b141 100644
--- a/chrome/browser/apps/app_service/publishers/plugin_vm_apps.h
+++ b/chrome/browser/apps/app_service/publishers/plugin_vm_apps.h
@@ -108,7 +108,7 @@
   mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
 
   Profile* const profile_;
-  guest_os::GuestOsRegistryService* registry_;
+  guest_os::GuestOsRegistryService* registry_ = nullptr;
 
   apps_util::IncrementingIconKeyFactory icon_key_factory_;
 
diff --git a/chrome/browser/apps/app_service/publishers/publisher_unittest.cc b/chrome/browser/apps/app_service/publishers/publisher_unittest.cc
index 9078d2a..4222ce3 100644
--- a/chrome/browser/apps/app_service/publishers/publisher_unittest.cc
+++ b/chrome/browser/apps/app_service/publishers/publisher_unittest.cc
@@ -642,7 +642,7 @@
 
 class StandaloneBrowserPublisherTest : public PublisherTest {
  public:
-  StandaloneBrowserPublisherTest() : PublisherTest() {
+  StandaloneBrowserPublisherTest() {
     crosapi::browser_util::SetLacrosEnabledForTest(true);
     scoped_feature_list_.Reset();
     scoped_feature_list_.InitWithFeatures(
diff --git a/chrome/browser/apps/app_service/subscriber_crosapi.cc b/chrome/browser/apps/app_service/subscriber_crosapi.cc
index 6ed1893..d90dd72 100644
--- a/chrome/browser/apps/app_service/subscriber_crosapi.cc
+++ b/chrome/browser/apps/app_service/subscriber_crosapi.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/webui/settings/ash/app_management/app_management_uma.h"
-#include "chrome/common/chrome_features.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
@@ -184,19 +183,10 @@
     return;
   }
 
-  auto app_type = proxy_->AppRegistryCache().GetAppType(app_id);
-  if (base::FeatureList::IsEnabled(features::kAppServiceLoadIconWithoutMojom)) {
-    proxy_->LoadIconFromIconKey(
-        app_type, app_id, *icon_key, icon_type, size_hint_in_dip,
-        /*allow_placeholder_icon=*/false, std::move(callback));
-  } else {
-    proxy_->LoadIconFromIconKey(
-        ConvertAppTypeToMojomAppType(app_type), app_id,
-        ConvertIconKeyToMojomIconKey(*icon_key),
-        ConvertIconTypeToMojomIconType(icon_type), size_hint_in_dip,
-        /*allow_placeholder_icon=*/false,
-        MojomIconValueToIconValueCallback(std::move(callback)));
-  }
+  proxy_->LoadIconFromIconKey(proxy_->AppRegistryCache().GetAppType(app_id),
+                              app_id, *icon_key, icon_type, size_hint_in_dip,
+                              /*allow_placeholder_icon=*/false,
+                              std::move(callback));
 }
 
 void SubscriberCrosapi::AddPreferredApp(const std::string& app_id,
diff --git a/chrome/browser/apps/app_service/uninstall_dialog.cc b/chrome/browser/apps/app_service/uninstall_dialog.cc
index 3ae3c20..4d82c56 100644
--- a/chrome/browser/apps/app_service/uninstall_dialog.cc
+++ b/chrome/browser/apps/app_service/uninstall_dialog.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/apps/app_service/publishers/extension_apps_chromeos.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/native_window_tracker.h"
-#include "chrome/common/chrome_features.h"
 #include "components/services/app_service/public/cpp/icon_loader.h"
 #include "extensions/browser/uninstall_reason.h"
 
@@ -64,25 +63,12 @@
       return;
   }
 
-  constexpr bool kAllowPlaceholderIcon = false;
   // Currently ARC apps only support 48*48 native icon.
-  int32_t size_hint_in_dip = kUninstallIconSize;
-  if (base::FeatureList::IsEnabled(features::kAppServiceLoadIconWithoutMojom)) {
-    auto icon_type = IconType::kStandard;
-    icon_loader->LoadIconFromIconKey(
-        app_type_, app_id_, icon_key, icon_type, size_hint_in_dip,
-        kAllowPlaceholderIcon,
-        base::BindOnce(&UninstallDialog::OnLoadIcon,
-                       weak_ptr_factory_.GetWeakPtr()));
-  } else {
-    auto mojom_icon_type = apps::mojom::IconType::kStandard;
-    icon_loader->LoadIconFromIconKey(
-        ConvertAppTypeToMojomAppType(app_type_), app_id_,
-        ConvertIconKeyToMojomIconKey(icon_key), mojom_icon_type,
-        size_hint_in_dip, kAllowPlaceholderIcon,
-        MojomIconValueToIconValueCallback(base::BindOnce(
-            &UninstallDialog::OnLoadIcon, weak_ptr_factory_.GetWeakPtr())));
-  }
+  icon_loader->LoadIconFromIconKey(
+      app_type_, app_id_, icon_key, IconType::kStandard, kUninstallIconSize,
+      /*allow_placeholder_icon=*/false,
+      base::BindOnce(&UninstallDialog::OnLoadIcon,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 views::Widget* UninstallDialog::GetWidget() {
diff --git a/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc b/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc
index 3e408fd..c2a0abf 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc
@@ -20,8 +20,7 @@
 namespace apps {
 
 // Queue of WebApks to be installed or updated.
-WebApkInstallQueue::WebApkInstallQueue(Profile* profile)
-    : profile_(profile), connection_ready_(false) {
+WebApkInstallQueue::WebApkInstallQueue(Profile* profile) : profile_(profile) {
   arc::ArcServiceManager* arc_service_manager = arc::ArcServiceManager::Get();
   DCHECK(arc_service_manager);
   arc_service_manager->arc_bridge_service()->webapk()->AddObserver(this);
diff --git a/chrome/browser/apps/app_service/webapk/webapk_install_queue.h b/chrome/browser/apps/app_service/webapk/webapk_install_queue.h
index fc55b8a..24ae4364 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_install_queue.h
+++ b/chrome/browser/apps/app_service/webapk/webapk_install_queue.h
@@ -48,7 +48,7 @@
   Profile* profile_;
   base::circular_deque<std::unique_ptr<WebApkInstallTask>> pending_installs_;
   std::unique_ptr<WebApkInstallTask> current_install_;
-  bool connection_ready_;
+  bool connection_ready_ = false;
 
   base::WeakPtrFactory<WebApkInstallQueue> weak_ptr_factory_{this};
 };
diff --git a/chrome/browser/apps/app_service/webapk/webapk_manager.cc b/chrome/browser/apps/app_service/webapk/webapk_manager.cc
index 3ef17c89..a0d864a 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_manager.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_manager.cc
@@ -50,7 +50,6 @@
 
 WebApkManager::WebApkManager(Profile* profile)
     : profile_(profile),
-      initialized_(false),
       install_queue_(std::make_unique<WebApkInstallQueue>(profile_)),
       pref_change_registrar_(std::make_unique<PrefChangeRegistrar>()) {
   DCHECK(web_app::AreWebAppsEnabled(profile_));
diff --git a/chrome/browser/apps/app_service/webapk/webapk_manager.h b/chrome/browser/apps/app_service/webapk/webapk_manager.h
index 0b8eb2a9..323b331 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_manager.h
+++ b/chrome/browser/apps/app_service/webapk/webapk_manager.h
@@ -72,7 +72,7 @@
   ash::ApkWebAppService* apk_service_;
   ArcAppListPrefs* app_list_prefs_;
 
-  bool initialized_;
+  bool initialized_ = false;
 
   std::unique_ptr<WebApkInstallQueue> install_queue_;
   std::vector<std::string> uninstall_queue_;
diff --git a/chrome/browser/apps/intent_helper/common_apps_navigation_throttle.cc b/chrome/browser/apps/intent_helper/common_apps_navigation_throttle.cc
index d73adf8..849a8602 100644
--- a/chrome/browser/apps/intent_helper/common_apps_navigation_throttle.cc
+++ b/chrome/browser/apps/intent_helper/common_apps_navigation_throttle.cc
@@ -204,7 +204,7 @@
   auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile);
 
   std::vector<std::string> app_ids =
-      proxy->GetAppIdsForUrl(url, /*exclude_browser=*/true);
+      proxy->GetAppIdsForUrl(url, /*exclude_browsers=*/true);
 
   if (app_ids.empty())
     return false;
@@ -279,7 +279,7 @@
       Profile::FromBrowserContext(web_contents->GetBrowserContext());
   std::vector<std::string> app_ids =
       apps::AppServiceProxyFactory::GetForProfile(profile)->GetAppIdsForUrl(
-          url, /*exclude_browser=*/true, /*exclude_browser_tab_apps=*/false);
+          url, /*exclude_browsers=*/true, /*exclude_browser_tab_apps=*/false);
 
   for (auto app_id : app_ids) {
     if (IsAppDisabled(app_id)) {
diff --git a/chrome/browser/ash/accessibility/dictation_browsertest.cc b/chrome/browser/ash/accessibility/dictation_browsertest.cc
index 9c99eb96..f799e5a 100644
--- a/chrome/browser/ash/accessibility/dictation_browsertest.cc
+++ b/chrome/browser/ash/accessibility/dictation_browsertest.cc
@@ -348,7 +348,7 @@
     SendFinalResultAndWait(result);
     // TODO(https://crbug.com/1333354): Investigate why this does not always
     // return true.
-    std::ignore = waiter.WaitForNotification();
+    ASSERT_TRUE(waiter.WaitForNotification());
     WaitForTextAreaValue(value);
   }
 
@@ -363,7 +363,7 @@
     bounding_box_waiter.Wait();
     // TODO(https://crbug.com/1333354): Investigate why this does not always
     // return true.
-    std::ignore = selection_waiter.WaitForNotification();
+    ASSERT_TRUE(selection_waiter.WaitForNotification());
   }
 
   void SendFinalResultAndWaitForCaretBoundsChanged(const std::string& result) {
@@ -376,7 +376,7 @@
     caret_waiter.Wait();
     // TODO(https://crbug.com/1333354): Investigate why this does not always
     // return true.
-    std::ignore = selection_waiter.WaitForNotification();
+    ASSERT_TRUE(selection_waiter.WaitForNotification());
   }
 
   void SendFinalResultAndWaitForClipboardChanged(const std::string& result) {
@@ -1197,7 +1197,7 @@
         browser()->window()->GetNativeWindow()->GetHost()->GetInputMethod());
     RunHiddenMacro(macro);
     caret_waiter.Wait();
-    std::ignore = selection_waiter.WaitForNotification();
+    ASSERT_TRUE(selection_waiter.WaitForNotification());
   }
 
   void RunSmartSelectMacroAndWaitForSelectionChanged(
diff --git a/chrome/browser/ash/arc/input_overlay/actions/action_move.cc b/chrome/browser/ash/arc/input_overlay/actions/action_move.cc
index f56c562..9bfdc1f 100644
--- a/chrome/browser/ash/arc/input_overlay/actions/action_move.cc
+++ b/chrome/browser/ash/arc/input_overlay/actions/action_move.cc
@@ -166,11 +166,19 @@
     if (ShouldShowErrorMsg(code, action_label))
       return;
 
-    auto& binding = action_->GetCurrentDisplayedBinding();
+    const auto& binding = action_->GetCurrentDisplayedBinding();
     DCHECK(binding.keys().size() == kActionMoveKeysSize);
-    const int index = it - labels_.begin();
     std::vector<ui::DomCode> new_keys = binding.keys();
-    new_keys[index] = code;
+    new_keys[it - labels_.begin()] = code;
+
+    // If there is duplicate key in its own action, take the key away from
+    // previous index.
+    const int unassigned_index = binding.GetIndexOfKey(code);
+    if (unassigned_index != -1) {
+      new_keys[unassigned_index] = ui::DomCode::NONE;
+      labels_[unassigned_index]->SetDisplayMode(DisplayMode::kEditedUnbound);
+    }
+
     auto input_element = InputElement::CreateActionMoveKeyElement(new_keys);
     ChangeBinding(action_, action_label, std::move(input_element));
   }
diff --git a/chrome/browser/ash/arc/input_overlay/actions/input_element.cc b/chrome/browser/ash/arc/input_overlay/actions/input_element.cc
index 7e4c341..c818de5 100644
--- a/chrome/browser/ash/arc/input_overlay/actions/input_element.cc
+++ b/chrome/browser/ash/arc/input_overlay/actions/input_element.cc
@@ -181,6 +181,11 @@
   std::copy(keys.begin(), keys.end(), std::back_inserter(keys_));
 }
 
+int InputElement::GetIndexOfKey(ui::DomCode key) const {
+  auto it = std::find(keys_.begin(), keys_.end(), key);
+  return it == keys_.end() ? -1 : it - keys_.begin();
+}
+
 std::unique_ptr<InputElementProto> InputElement::ConvertToProto() {
   auto proto = std::make_unique<InputElementProto>();
   proto->set_input_sources(input_sources_);
diff --git a/chrome/browser/ash/arc/input_overlay/actions/input_element.h b/chrome/browser/ash/arc/input_overlay/actions/input_element.h
index 2fcb623..8648747 100644
--- a/chrome/browser/ash/arc/input_overlay/actions/input_element.h
+++ b/chrome/browser/ash/arc/input_overlay/actions/input_element.h
@@ -67,6 +67,9 @@
   void SetKey(int index, ui::DomCode code);
   // Set keys to |keys|.
   void SetKeys(std::vector<ui::DomCode>& keys);
+  // If it is keyboard-binded input and there is |key| binded, return the index
+  // of the |key|. Otherwise, return -1;
+  int GetIndexOfKey(ui::DomCode key) const;
   std::unique_ptr<InputElementProto> ConvertToProto();
 
   int input_sources() const { return input_sources_; }
diff --git a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc
index bc16a47..45ea981c 100644
--- a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc
+++ b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc
@@ -416,8 +416,7 @@
   action_edit_menu_ = nullptr;
 }
 
-void DisplayOverlayController::AddEditMessage(ActionView* action_view,
-                                              const base::StringPiece& message,
+void DisplayOverlayController::AddEditMessage(const base::StringPiece& message,
                                               MessageType message_type) {
   RemoveEditMessage();
   auto* overlay_widget = GetOverlayWidget();
diff --git a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h
index e6f1740..a0206dca 100644
--- a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h
+++ b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.h
@@ -55,8 +55,7 @@
   void AddActionEditMenu(ActionView* anchor, ActionType action_type);
   void RemoveActionEditMenu();
 
-  void AddEditMessage(ActionView* action_view,
-                      const base::StringPiece& message,
+  void AddEditMessage(const base::StringPiece& message,
                       MessageType message_type);
   void RemoveEditMessage();
 
diff --git a/chrome/browser/ash/arc/input_overlay/ui/action_label.cc b/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
index f4f7b30..e3846033 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
@@ -7,7 +7,6 @@
 #include <set>
 
 #include "ash/style/style_util.h"
-#include "base/strings/string_piece.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ash/arc/input_overlay/ui/action_label.h"
 #include "chrome/browser/ash/arc/input_overlay/ui/action_view.h"
@@ -198,6 +197,8 @@
     case DisplayMode::kEdit:
       SetToEditMode();
       SetFocusBehavior(FocusBehavior::ALWAYS);
+      static_cast<ActionView*>(parent())->ShowInfoMsg(
+          l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_INSTRUCTIONS), this);
       break;
     case DisplayMode::kEditedSuccess:
       SetToEditFocus();
@@ -265,14 +266,10 @@
   LabelButton::OnFocus();
   if (IsUnbound()) {
     static_cast<ActionView*>(parent())->ShowErrorMsg(
-        base::StringPiece(
-            l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_MISSING_BINDING)),
-        this);
+        l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_MISSING_BINDING), this);
   } else {
     static_cast<ActionView*>(parent())->ShowInfoMsg(
-        base::StringPiece(
-            l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_FOCUSED_KEY)),
-        this);
+        l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_FOCUSED_KEY), this);
   }
 }
 
@@ -283,6 +280,10 @@
 }
 
 void ActionLabel::SetToViewMode() {
+  if (IsUnbound()) {
+    SetVisible(false);
+    return;
+  }
   ClearFocus();
   SetInstallFocusRingOnFocus(false);
   label()->SetFontList(gfx::FontList({kFontStyle}, gfx::Font::NORMAL, kFontSize,
@@ -309,6 +310,9 @@
 }
 
 void ActionLabel::SetToEditMode() {
+  if (IsUnbound())
+    SetVisible(true);
+
   SetInstallFocusRingOnFocus(true);
   auto* focus_ring = views::FocusRing::Get(this);
   focus_ring->SetHaloInset(kHaloInset);
diff --git a/chrome/browser/ash/arc/input_overlay/ui/action_view.cc b/chrome/browser/ash/arc/input_overlay/ui/action_view.cc
index 90ebe11..8a760e1 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/action_view.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/action_view.cc
@@ -14,11 +14,6 @@
 namespace {
 constexpr int kMenuEntryOffset = 4;
 
-// UI strings.
-// TODO(cuicuiruan): Remove string and related code.
-constexpr base::StringPiece kEditErrorDuplicatedKey(
-    "Duplicated key in the same action");
-
 // For the keys that are caught by display overlay, check if they are reserved
 // for special use.
 bool IsReservedDomCode(ui::DomCode code) {
@@ -105,15 +100,13 @@
 
 void ActionView::ShowErrorMsg(const base::StringPiece& message,
                               ActionLabel* editing_label) {
-  display_overlay_controller_->AddEditMessage(this, message,
-                                              MessageType::kError);
+  display_overlay_controller_->AddEditMessage(message, MessageType::kError);
   SetDisplayMode(DisplayMode::kEditedError, editing_label);
 }
 
 void ActionView::ShowInfoMsg(const base::StringPiece& message,
                              ActionLabel* editing_label) {
-  display_overlay_controller_->AddEditMessage(this, message,
-                                              MessageType::kInfo);
+  display_overlay_controller_->AddEditMessage(message, MessageType::kInfo);
 }
 
 void ActionView::RemoveMessage() {
@@ -163,23 +156,10 @@
 
 bool ActionView::ShouldShowErrorMsg(ui::DomCode code,
                                     ActionLabel* editing_label) {
-  // Check if |code| is duplicated with the keys in its action. For example,
-  // there are four keys involved in the key-bound |ActionMove|.
-  auto& binding = action_->GetCurrentDisplayedBinding();
-  if (IsKeyboardBound(binding)) {
-    for (const auto& key : binding.keys()) {
-      if (key != code)
-        continue;
-      ShowErrorMsg(kEditErrorDuplicatedKey, editing_label);
-      return true;
-    }
-  }
-
   if ((!action_->support_modifier_key() &&
        ModifierDomCodeToEventFlag(code) != ui::EF_NONE) ||
       IsReservedDomCode(code)) {
-    ShowErrorMsg(base::StringPiece(l10n_util::GetStringUTF8(
-                     IDS_INPUT_OVERLAY_EDIT_RESERVED_KEYS)),
+    ShowErrorMsg(l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_RESERVED_KEYS),
                  editing_label);
     return true;
   }
diff --git a/chrome/browser/ash/arc/input_overlay/ui/input_mapping_view.cc b/chrome/browser/ash/arc/input_overlay/ui/input_mapping_view.cc
index af476a69f..a5087a6 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/input_mapping_view.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/input_mapping_view.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ash/arc/input_overlay/ui/input_mapping_view.h"
 
+#include "chrome/grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/views/background.h"
 
 namespace arc {
@@ -64,6 +66,9 @@
       auto bounds = action_label->GetBoundsInScreen();
       if (!bounds.Contains(event_location)) {
         action_label->ClearFocus();
+        display_overlay_controller_->AddEditMessage(
+            l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_INSTRUCTIONS),
+            MessageType::kInfo);
         break;
       }
     }
diff --git a/chrome/browser/ash/bruschetta/DIR_METADATA b/chrome/browser/ash/bruschetta/DIR_METADATA
index f461eb4..06e627f 100644
--- a/chrome/browser/ash/bruschetta/DIR_METADATA
+++ b/chrome/browser/ash/bruschetta/DIR_METADATA
@@ -1,3 +1 @@
-monorail: {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/ash/camera_mic/DIR_METADATA b/chrome/browser/ash/camera_mic/DIR_METADATA
index f461eb4..06e627f 100644
--- a/chrome/browser/ash/camera_mic/DIR_METADATA
+++ b/chrome/browser/ash/camera_mic/DIR_METADATA
@@ -1,3 +1 @@
-monorail: {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_util.h b/chrome/browser/ash/crosapi/browser_data_migrator_util.h
index d76ab62..50d2ef3 100644
--- a/chrome/browser/ash/crosapi/browser_data_migrator_util.h
+++ b/chrome/browser/ash/crosapi/browser_data_migrator_util.h
@@ -174,6 +174,7 @@
     "Session Storage",
     "Sessions",
     "Shortcuts",
+    "Storage",
     "Sync App Settings",
     "Sync Extension Settings",
     "Top Sites",
@@ -239,6 +240,10 @@
     "Extension State",
 };
 
+// `Storage` path.
+constexpr char kStorageFilePath[] = "Storage";
+constexpr char kStorageExtFilePath[] = "ext";
+
 // The type of LevelDB schema.
 enum class LevelDBType {
   kLocalStorage = 0,
diff --git a/chrome/browser/ash/crosapi/move_migrator.cc b/chrome/browser/ash/crosapi/move_migrator.cc
index b4620c4..8260de7 100644
--- a/chrome/browser/ash/crosapi/move_migrator.cc
+++ b/chrome/browser/ash/crosapi/move_migrator.cc
@@ -404,35 +404,22 @@
   }
 
   // Copy extensions that have to be in both Ash and Lacros.
-  const base::FilePath original_extensions_dir = original_profile_dir.Append(
-      browser_data_migrator_util::kExtensionsFilePath);
-  if (base::PathExists(original_extensions_dir)) {
-    const base::FilePath split_extensions_dir =
-        tmp_split_dir.Append(browser_data_migrator_util::kExtensionsFilePath);
-    if (!base::CreateDirectory(split_extensions_dir)) {
-      PLOG(ERROR) << "CreateDirectory() failed for  "
-                  << split_extensions_dir.value();
-      return {TaskStatus::kSetupAshDirCreateDirFailed, errno};
-    }
+  TaskResult task_result =
+      CopyBothChromesSubdirs(original_profile_dir, tmp_split_dir,
+                             browser_data_migrator_util::kExtensionsFilePath,
+                             TaskStatus::kSetupAshDirCopyExtensionsFailed);
+  if (task_result.status != TaskStatus::kSucceeded)
+    return task_result;
 
-    for (const char* extension_id :
-         browser_data_migrator_util::kExtensionsBothChromes) {
-      base::FilePath original_extension_path =
-          original_extensions_dir.Append(extension_id);
-
-      if (base::PathExists(original_extension_path)) {
-        base::FilePath split_extension_path =
-            split_extensions_dir.Append(extension_id);
-
-        if (!base::CopyDirectory(original_extension_path, split_extension_path,
-                                 /*recursive=*/true)) {
-          PLOG(ERROR) << "Failed copying " << original_extension_path.value()
-                      << " to " << split_extension_path.value();
-          return {TaskStatus::kSetupAshDirCopyExtensionsFailed, errno};
-        }
-      }
-    }
-  }
+  // Copy Storage objects for extensions that have to be both in Ash and Lacros.
+  task_result = CopyBothChromesSubdirs(
+      original_profile_dir, tmp_split_dir,
+      base::FilePath(browser_data_migrator_util::kStorageFilePath)
+          .Append(browser_data_migrator_util::kStorageExtFilePath)
+          .value(),
+      TaskStatus::kSetupAshDirCopyStorageFailed);
+  if (task_result.status != TaskStatus::kSucceeded)
+    return task_result;
 
   // Copy IndexedDB objects for extensions that have to be both in
   // Ash and Lacros.
@@ -637,32 +624,23 @@
   }
 
   // Move extensions in the keeplist back to Ash's profile directory.
-  const base::FilePath lacros_extensions_dir =
-      tmp_profile_dir.Append(browser_data_migrator_util::kExtensionsFilePath);
-  if (base::PathExists(lacros_extensions_dir)) {
-    const base::FilePath ash_extensions_dir = original_profile_dir.Append(
-        browser_data_migrator_util::kExtensionsFilePath);
-    if (!base::CreateDirectory(ash_extensions_dir)) {
-      PLOG(ERROR) << "CreateDirectory() failed for  "
-                  << ash_extensions_dir.value();
-      return {TaskStatus::kMoveSplitItemsToOriginalDirCreateDirFailed, errno};
-    }
+  TaskResult task_result = MoveAshSubdirs(
+      tmp_profile_dir, original_profile_dir,
+      browser_data_migrator_util::kExtensionsFilePath,
+      TaskStatus::kMoveSplitItemsToOriginalDirMoveExtensionsFailed);
+  if (task_result.status != TaskStatus::kSucceeded)
+    return task_result;
 
-    // Move Ash-only extensions.
-    for (const char* extension_id :
-         browser_data_migrator_util::kExtensionsAshOnly) {
-      base::FilePath lacros_path = lacros_extensions_dir.Append(extension_id);
-      if (base::PathExists(lacros_path)) {
-        base::FilePath ash_path = ash_extensions_dir.Append(extension_id);
-        if (!base::Move(lacros_path, ash_path)) {
-          PLOG(ERROR) << "Failed moving " << lacros_path.value() << " to "
-                      << ash_path.value();
-          return {TaskStatus::kMoveSplitItemsToOriginalDirMoveExtensionsFailed,
-                  errno};
-        }
-      }
-    }
-  }
+  // Move Storage objects related to extensions in the keeplist back to Ash's
+  // profile directory.
+  task_result = MoveAshSubdirs(
+      tmp_profile_dir, original_profile_dir,
+      base::FilePath(browser_data_migrator_util::kStorageFilePath)
+          .Append(browser_data_migrator_util::kStorageExtFilePath)
+          .value(),
+      TaskStatus::kMoveSplitItemsToOriginalDirMoveStorageFailed);
+  if (task_result.status != TaskStatus::kSucceeded)
+    return task_result;
 
   // Move IndexedDB objects related to extensions in the keeplist back to Ash's
   // profile directory.
@@ -750,6 +728,80 @@
   InvokeCallback(result);
 }
 
+// static
+MoveMigrator::TaskResult MoveMigrator::CopyBothChromesSubdirs(
+    const base::FilePath& original_profile_dir,
+    const base::FilePath& tmp_split_dir,
+    const std::string& target_dir,
+    TaskStatus copy_fail_status) {
+  const base::FilePath original_target_dir =
+      original_profile_dir.Append(target_dir);
+
+  if (base::PathExists(original_target_dir)) {
+    const base::FilePath split_target_dir = tmp_split_dir.Append(target_dir);
+    if (!base::CreateDirectory(split_target_dir)) {
+      PLOG(ERROR) << "CreateDirectory() failed for  "
+                  << split_target_dir.value();
+      return {TaskStatus::kSetupAshDirCreateDirFailed, errno};
+    }
+
+    // Copy objects that belong to both Ash and Lacros.
+    for (const char* extension_id :
+         browser_data_migrator_util::kExtensionsBothChromes) {
+      base::FilePath original_target_path =
+          original_target_dir.Append(extension_id);
+
+      if (base::PathExists(original_target_path)) {
+        base::FilePath split_target_path =
+            split_target_dir.Append(extension_id);
+
+        if (!base::CopyDirectory(original_target_path, split_target_path,
+                                 /*recursive=*/true)) {
+          PLOG(ERROR) << "Failed copying " << original_target_path.value()
+                      << " to " << split_target_path.value();
+          return {copy_fail_status, errno};
+        }
+      }
+    }
+  }
+
+  return {TaskStatus::kSucceeded};
+}
+
+// static
+MoveMigrator::TaskResult MoveMigrator::MoveAshSubdirs(
+    const base::FilePath& tmp_profile_dir,
+    const base::FilePath& original_profile_dir,
+    const std::string& target_dir,
+    TaskStatus move_fail_status) {
+  const base::FilePath lacros_target_dir = tmp_profile_dir.Append(target_dir);
+
+  if (base::PathExists(lacros_target_dir)) {
+    const base::FilePath ash_target_dir =
+        original_profile_dir.Append(target_dir);
+    if (!base::CreateDirectory(ash_target_dir)) {
+      PLOG(ERROR) << "CreateDirectory() failed for  " << ash_target_dir.value();
+      return {TaskStatus::kMoveSplitItemsToOriginalDirCreateDirFailed, errno};
+    }
+
+    // Move Ash-only objects.
+    for (const char* extension_id :
+         browser_data_migrator_util::kExtensionsAshOnly) {
+      base::FilePath lacros_path = lacros_target_dir.Append(extension_id);
+      if (base::PathExists(lacros_path)) {
+        base::FilePath ash_path = ash_target_dir.Append(extension_id);
+        if (!base::Move(lacros_path, ash_path)) {
+          PLOG(ERROR) << "Failed moving " << lacros_path.value() << " to "
+                      << ash_path.value();
+          return {move_fail_status, errno};
+        }
+      }
+    }
+  }
+
+  return {TaskStatus::kSucceeded};
+}
+
 void MoveMigrator::InvokeCallback(TaskResult result) {
   UMA_HISTOGRAM_ENUMERATION(kMoveMigratorTaskStatusUMA, result.status);
   if (result.status != TaskStatus::kSucceeded &&
@@ -798,6 +850,8 @@
     case TaskStatus::kSetupAshDirCopyExtensionsFailed:
     case TaskStatus::kSetupAshDirCopyIndexedDBFailed:
     case TaskStatus::kSetupAshDirMigrateSyncDataFailed:
+    case TaskStatus::kSetupAshDirCopyStorageFailed:
+    case TaskStatus::kMoveSplitItemsToOriginalDirMoveStorageFailed:
       return {BrowserDataMigratorImpl::DataWipeResult::kSucceeded,
               {BrowserDataMigratorImpl::ResultKind::kFailed}};
   }
@@ -845,6 +899,8 @@
     MAPPING(SetupAshDirCopyExtensionsFailed);
     MAPPING(SetupAshDirCopyIndexedDBFailed);
     MAPPING(SetupAshDirMigrateSyncDataFailed);
+    MAPPING(SetupAshDirCopyStorageFailed);
+    MAPPING(MoveSplitItemsToOriginalDirMoveStorageFailed);
 #undef MAPPING
   }
 }
diff --git a/chrome/browser/ash/crosapi/move_migrator.h b/chrome/browser/ash/crosapi/move_migrator.h
index 902e7af..d6d108ab 100644
--- a/chrome/browser/ash/crosapi/move_migrator.h
+++ b/chrome/browser/ash/crosapi/move_migrator.h
@@ -173,7 +173,9 @@
     kSetupAshDirCopyExtensionsFailed = 22,
     kSetupAshDirCopyIndexedDBFailed = 23,
     kSetupAshDirMigrateSyncDataFailed = 24,
-    kMaxValue = kSetupAshDirMigrateSyncDataFailed,
+    kSetupAshDirCopyStorageFailed = 25,
+    kMoveSplitItemsToOriginalDirMoveStorageFailed = 26,
+    kMaxValue = kMoveSplitItemsToOriginalDirMoveStorageFailed,
   };
 
   struct TaskResult {
@@ -268,6 +270,25 @@
   // Called as a reply to `MoveTmpDirToLacrosDir()`.
   void OnMoveTmpDirToLacrosDir(TaskResult);
 
+  // Selectively copy `target_dir` from `original_profile_dir` to
+  // `tmp_split_dir`. Only copy the subdirectories belonging to extensions
+  // that have to stay in both Ash and Lacros.
+  // If copying fails, return a TaskResult with `copy_fail_status` TaskStatus.
+  static TaskResult CopyBothChromesSubdirs(
+      const base::FilePath& original_profile_dir,
+      const base::FilePath& tmp_split_dir,
+      const std::string& target_dir,
+      TaskStatus copy_fail_status);
+
+  // Selectively move `target_dir` from `tmp_profile_dir` to
+  // `original_profile_dir`. Only move the subdirectories belonging to
+  // extensions that have to be in Ash only.
+  // If moving fails, return a TaskResult with `move_fail_status` TaskStatus.
+  static TaskResult MoveAshSubdirs(const base::FilePath& tmp_profile_dir,
+                                   const base::FilePath& original_profile_dir,
+                                   const std::string& target_dir,
+                                   TaskStatus move_fail_status);
+
   // Records the final status of the migration in `kMoveMigratorTaskStatusUMA`
   // and calls `finished_callback_`. This function gets called once regardless
   // of whether the migration succeeded or not.
diff --git a/chrome/browser/ash/crosapi/move_migrator_unittest.cc b/chrome/browser/ash/crosapi/move_migrator_unittest.cc
index 8a1d0748..b51a931a 100644
--- a/chrome/browser/ash/crosapi/move_migrator_unittest.cc
+++ b/chrome/browser/ash/crosapi/move_migrator_unittest.cc
@@ -106,6 +106,50 @@
   }
 }
 
+// Setup the `Storage` folder inside a profile.
+// If `ash_only` is true, it will only generate data associated to extensions
+// that have to be kept in Ash. Otherwise, it will generate data for both
+// categories of extensions.
+void SetUpStorage(const base::FilePath& profile_path,
+                  bool ash = true,
+                  bool lacros = true,
+                  bool both = true) {
+  base::FilePath path =
+      profile_path.Append(browser_data_migrator_util::kStorageFilePath)
+          .Append(browser_data_migrator_util::kStorageExtFilePath);
+
+  // Generate data for an extension that has to be moved to Lacros.
+  if (lacros) {
+    ASSERT_TRUE(base::CreateDirectory(path.Append(kMoveExtensionId)));
+    ASSERT_EQ(
+        base::WriteFile(path.Append(kMoveExtensionId).Append(kDataFilePath),
+                        kDataContent, kDataSize),
+        kDataSize);
+  }
+
+  // Generate data for an extension that has to stay in Ash.
+  if (ash) {
+    std::string keep_extension_id =
+        browser_data_migrator_util::kExtensionsAshOnly[0];
+    ASSERT_TRUE(base::CreateDirectory(path.Append(keep_extension_id)));
+    ASSERT_EQ(
+        base::WriteFile(path.Append(keep_extension_id).Append(kDataFilePath),
+                        kDataContent, kDataSize),
+        kDataSize);
+  }
+
+  // Generate data for an extension that has to be in both Ash and Lacros.
+  if (both) {
+    std::string both_extension_id =
+        browser_data_migrator_util::kExtensionsBothChromes[0];
+    ASSERT_TRUE(base::CreateDirectory(path.Append(both_extension_id)));
+    ASSERT_EQ(
+        base::WriteFile(path.Append(both_extension_id).Append(kDataFilePath),
+                        kDataContent, kDataSize),
+        kDataSize);
+  }
+}
+
 // Setup the `Local Storage` folder inside a profile.
 // If `ash_only` is true, it will only generate data associated to extensions
 // that have to be kept in Ash. Otherwise, it will generate data for both
@@ -304,6 +348,7 @@
   // |- Login Data/
   // |- Policy/
   // |- Preferences
+  // |- Storage/
   // |- Sync Data/
   ASSERT_TRUE(base::CreateDirectory(path.Append(kCacheFilePath)));
   ASSERT_EQ(base::WriteFile(path.Append(kCacheFilePath).Append(kDataFilePath),
@@ -331,6 +376,7 @@
             kDataSize);
 
   SetUpExtensions(path);
+  SetUpStorage(path);
   SetUpLocalStorage(path);
   SetUpExtensionState(path);
   SetUpIndexedDB(path);
@@ -681,6 +727,7 @@
     // |- Login Data
     // |- Policy
     // |- Preferences
+    // |- Storage/
     // |- Sync Data
     // |- lacros/First Run
     // |- lacros/Default/
@@ -691,6 +738,7 @@
     //     |- Local Storage
     //     |- Policy
     //     |- Preferences
+    //     |- Storage/
     //     |- Sync Data
 
     const base::FilePath new_user_dir =
@@ -742,6 +790,27 @@
         new_profile_dir.Append(browser_data_migrator_util::kExtensionsFilePath)
             .Append(kMoveExtensionId)));
 
+    // Storage.
+    EXPECT_TRUE(base::PathExists(
+        original_profile_dir_
+            .Append(browser_data_migrator_util::kStorageFilePath)
+            .Append(browser_data_migrator_util::kStorageExtFilePath)
+            .Append(keep_extension_id)));
+    EXPECT_TRUE(base::PathExists(
+        original_profile_dir_
+            .Append(browser_data_migrator_util::kStorageFilePath)
+            .Append(browser_data_migrator_util::kStorageExtFilePath)
+            .Append(both_extension_id)));
+    EXPECT_FALSE(base::PathExists(
+        original_profile_dir_
+            .Append(browser_data_migrator_util::kStorageFilePath)
+            .Append(browser_data_migrator_util::kStorageExtFilePath)
+            .Append(kMoveExtensionId)));
+    EXPECT_TRUE(base::PathExists(
+        new_profile_dir.Append(browser_data_migrator_util::kStorageFilePath)
+            .Append(browser_data_migrator_util::kStorageExtFilePath)
+            .Append(kMoveExtensionId)));
+
     // Local Storage.
     const base::FilePath ash_local_storage_path =
         original_profile_dir_
@@ -870,12 +939,14 @@
   //     |- Local Storage
   //     |- Policy
   //     |- Preferences
+  //     |- Storage/
   //     |- Sync Data
   // |- move_migrator_split/
   //     |- Extensions
   //     |- IndexedDB
   //     |- Local Storage
   //     |- Preferences
+  //     |- Storage/
   //     |- Sync Data
 
   const base::FilePath tmp_user_dir =
@@ -909,6 +980,16 @@
           browser_data_migrator_util::kExtensionsFilePath),
       tmp_profile_dir.Append(browser_data_migrator_util::kExtensionsFilePath)));
 
+  // Storage objects that have to stay in both Ash and Lacros were copied to the
+  // split dir.
+  SetUpStorage(tmp_split_dir, /*ash=*/false, /*lacros=*/false,
+               /*both=*/true);
+  // Storage objects have been moved to Lacros's tmp dir.
+  ASSERT_TRUE(base::Move(
+      original_profile_dir_.Append(
+          browser_data_migrator_util::kStorageFilePath),
+      tmp_profile_dir.Append(browser_data_migrator_util::kStorageFilePath)));
+
   // IndexedDB objects that have to stay in both Ash and Lacros were copied to
   // the split dir.
   SetUpIndexedDB(tmp_split_dir, /*ash=*/false, /*lacros=*/false, /*both=*/true);
@@ -961,12 +1042,14 @@
   //     |- Local Storage
   //     |- Policy
   //     |- Preferences
+  //     |- Storage/
   //     |- Sync Data
   // |- move_migrator_split/
   //     |- Extensions
   //     |- IndexedDB
   //     |- Local Storage
   //     |- Preferences
+  //     |- Storage/
   //     |- Sync Data
 
   const base::FilePath tmp_user_dir =
@@ -1003,6 +1086,17 @@
           browser_data_migrator_util::kExtensionsFilePath),
       tmp_profile_dir.Append(browser_data_migrator_util::kExtensionsFilePath)));
 
+  // Storage objects that have to stay in both Ash and Lacros were copied to the
+  // split dir.
+  SetUpStorage(tmp_split_dir, /*ash=*/false, /*lacros=*/false,
+               /*both=*/true);
+  // Storage objects have been moved to Lacros's tmp dir, but not yet split and
+  // moved to Ash profile dir.
+  ASSERT_TRUE(base::Move(
+      original_profile_dir_.Append(
+          browser_data_migrator_util::kStorageFilePath),
+      tmp_profile_dir.Append(browser_data_migrator_util::kStorageFilePath)));
+
   // IndexedDB objects that have to stay in both Ash and Lacros were copied to
   // the split dir.
   SetUpIndexedDB(tmp_split_dir, /*ash=*/false, /*lacros=*/false, /*both=*/true);
@@ -1050,6 +1144,7 @@
   // |- Local Storage
   // |- Policy
   // |- Preferences
+  // |- Storage/
   // |- Sync Data
   // |- move_migrator/First Run
   // |- move_migrator/Default/
@@ -1059,6 +1154,7 @@
   //     |- Local Storage
   //     |- Policy
   //     |- Preferences
+  //     |- Storage/
   //     |- Sync Data
 
   const base::FilePath tmp_user_dir =
@@ -1087,6 +1183,12 @@
   SetUpExtensions(tmp_profile_dir, /*ash=*/false, /*lacros=*/true);
   SetUpExtensions(original_profile_dir_, /*ash=*/true, /*lacros=*/false);
 
+  // Storage objects have been split, and Ash's version is in its final place.
+  ASSERT_TRUE(base::DeletePathRecursively(original_profile_dir_.Append(
+      browser_data_migrator_util::kStorageFilePath)));
+  SetUpStorage(tmp_profile_dir, /*ash=*/false, /*lacros=*/true);
+  SetUpStorage(original_profile_dir_, /*ash=*/true, /*lacros=*/false);
+
   // IndexedDB has been split, and Ash's version is in its final place.
   ASSERT_TRUE(base::DeletePathRecursively(original_profile_dir_.Append(
       browser_data_migrator_util::kIndexedDBFilePath)));
diff --git a/chrome/browser/ash/crostini/DIR_METADATA b/chrome/browser/ash/crostini/DIR_METADATA
index f461eb4..06e627f 100644
--- a/chrome/browser/ash/crostini/DIR_METADATA
+++ b/chrome/browser/ash/crostini/DIR_METADATA
@@ -1,3 +1 @@
-monorail: {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/ash/crostini/crostini_util.cc b/chrome/browser/ash/crostini/crostini_util.cc
index bd6f6cb..7b51777 100644
--- a/chrome/browser/ash/crostini/crostini_util.cc
+++ b/chrome/browser/ash/crostini/crostini_util.cc
@@ -248,8 +248,8 @@
 }
 
 bool IsCrostiniRunning(Profile* profile) {
-  return crostini::CrostiniManager::GetForProfile(profile)->IsVmRunning(
-      kCrostiniDefaultVmName);
+  auto* manager = crostini::CrostiniManager::GetForProfile(profile);
+  return manager && manager->IsVmRunning(kCrostiniDefaultVmName);
 }
 
 bool ShouldConfigureDefaultContainer(Profile* profile) {
diff --git a/chrome/browser/ash/dbus/ash_dbus_helper.cc b/chrome/browser/ash/dbus/ash_dbus_helper.cc
index de1cf9b..1fe45e1 100644
--- a/chrome/browser/ash/dbus/ash_dbus_helper.cc
+++ b/chrome/browser/ash/dbus/ash_dbus_helper.cc
@@ -39,6 +39,7 @@
 #include "chromeos/ash/components/hibernate/buildflags.h"  // ENABLE_HIBERNATE
 #include "chromeos/components/chromebox_for_meetings/buildflags/buildflags.h"  // PLATFORM_CFM
 #include "chromeos/dbus/anomaly_detector/anomaly_detector_client.h"
+#include "chromeos/dbus/arc/arc_appfuse_provider_client.h"
 #include "chromeos/dbus/arc/arc_camera_client.h"
 #include "chromeos/dbus/arc/arc_sensor_service_client.h"
 #include "chromeos/dbus/attestation/attestation_client.h"
@@ -111,6 +112,7 @@
   // NOTE: base::Feature is not initialized yet, so any non MultiProcessMash
   // dbus client initialization for Ash should be done in Shell::Init.
   InitializeDBusClient<chromeos::AnomalyDetectorClient>(bus);
+  InitializeDBusClient<chromeos::ArcAppfuseProviderClient>(bus);
   InitializeDBusClient<chromeos::ArcCameraClient>(bus);
   InitializeDBusClient<chromeos::ArcQuotaClient>(bus);
   InitializeDBusClient<chromeos::ArcSensorServiceClient>(bus);
@@ -260,6 +262,7 @@
   chromeos::AttestationClient::Shutdown();
   chromeos::ArcQuotaClient::Shutdown();
   chromeos::ArcCameraClient::Shutdown();
+  chromeos::ArcAppfuseProviderClient::Shutdown();
   chromeos::AnomalyDetectorClient::Shutdown();
 
   chromeos::DBusThreadManager::Shutdown();
diff --git a/chrome/browser/ash/exo/DIR_METADATA b/chrome/browser/ash/exo/DIR_METADATA
index f461eb4..06e627f 100644
--- a/chrome/browser/ash/exo/DIR_METADATA
+++ b/chrome/browser/ash/exo/DIR_METADATA
@@ -1,3 +1 @@
-monorail: {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/ash/guest_os/COMMON_METADATA b/chrome/browser/ash/guest_os/COMMON_METADATA
index f461eb4..abf128a 100644
--- a/chrome/browser/ash/guest_os/COMMON_METADATA
+++ b/chrome/browser/ash/guest_os/COMMON_METADATA
@@ -1,3 +1,11 @@
 monorail: {
+  project: "chromium"
   component: "UI>Shell>Containers"
 }
+buganizer: {
+  component_id: 658562   # ChromeOS > Software > Guest OS
+}
+buganizer_public: {
+  component_id: 1161264  # Chrome OS Public Tracker > Core Systems > Virtualization > Guests
+}
+team_email: "clumptini@google.com"
diff --git a/chrome/browser/ash/input_method/longpress_diacritics_suggester.cc b/chrome/browser/ash/input_method/longpress_diacritics_suggester.cc
index 753f94b..0d9d819 100644
--- a/chrome/browser/ash/input_method/longpress_diacritics_suggester.cc
+++ b/chrome/browser/ash/input_method/longpress_diacritics_suggester.cc
@@ -119,6 +119,7 @@
         new_index =
             (code == kNextDomCode) ? 0 : GetCurrentShownDiacritics().size() - 1;
       } else {
+        SetButtonHighlighted(*highlighted_index_, false);
         if (code == kNextDomCode) {
           new_index =
               (*highlighted_index_ + 1) % GetCurrentShownDiacritics().size();
@@ -128,7 +129,8 @@
                           : GetCurrentShownDiacritics().size() - 1;
         }
       }
-      SetButtonHighlighted(new_index);
+      SetButtonHighlighted(new_index, true);
+      highlighted_index_ = new_index;
       return SuggestionStatus::kBrowsing;
     default:
       return SuggestionStatus::kNotHandled;
@@ -214,7 +216,8 @@
   return {};
 }
 
-void LongpressDiacriticsSuggester::SetButtonHighlighted(size_t index) {
+void LongpressDiacriticsSuggester::SetButtonHighlighted(size_t index,
+                                                        bool highlighted) {
   if (!focused_context_id_.has_value()) {
     LOG(ERROR) << "suggest: Failed to set button highlighted. No context id.";
     return;
@@ -223,13 +226,11 @@
   suggestion_handler_->SetButtonHighlighted(
       *focused_context_id_,
       CreateButtonFor(index, GetCurrentShownDiacritics()[index]),
-      /* highlighted=*/true, &error);
+      /* highlighted=*/highlighted, &error);
 
   if (!error.empty()) {
     LOG(ERROR) << "suggest: Failed to set button highlighted. " << error;
   }
-
-  highlighted_index_ = index;
 }
 
 std::vector<std::u16string>
diff --git a/chrome/browser/ash/input_method/longpress_diacritics_suggester.h b/chrome/browser/ash/input_method/longpress_diacritics_suggester.h
index b11a3ab..5937c14 100644
--- a/chrome/browser/ash/input_method/longpress_diacritics_suggester.h
+++ b/chrome/browser/ash/input_method/longpress_diacritics_suggester.h
@@ -72,7 +72,7 @@
   std::vector<ime::TextSuggestion> GetSuggestions() override;
 
  private:
-  void SetButtonHighlighted(size_t index);
+  void SetButtonHighlighted(size_t index, bool highlighted);
   void Reset();
   std::vector<std::u16string> GetCurrentShownDiacritics();
   SuggestionHandlerInterface* const suggestion_handler_;
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
index b1591a1..93ad9ff 100644
--- a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
+++ b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
@@ -517,6 +517,32 @@
   }
 }
 
+void MigratePinyinAndZhuyinSettings(PrefService* prefs,
+                                    const std::string& engine_id) {
+  // We are using legacy pref keys for pinyin and zhuyin. To get rid of them, we
+  // need to write existing settings under the correct pref keys as the first
+  // step.
+  // TODO(b/175085612): Remove this function once we have migrated from the
+  // legacy pref keys.
+  if (engine_id != "zh-t-i0-pinyin" && engine_id != "zh-hant-t-i0-und")
+    return;
+
+  const base::Value& all_input_method_pref =
+      *prefs->GetDictionary(::prefs::kLanguageInputMethodSpecificSettings);
+
+  // Check if the settings are already migrated.
+  if (all_input_method_pref.FindDictKey(engine_id))
+    return;
+
+  const base::Value* existing_pref_or_null = all_input_method_pref.FindDictKey(
+      engine_id == "zh-t-i0-pinyin" ? "pinyin" : "zhuyin");
+  if (existing_pref_or_null) {
+    DictionaryPrefUpdate update(prefs,
+                                ::prefs::kLanguageInputMethodSpecificSettings);
+    update->SetPath(engine_id, existing_pref_or_null->Clone());
+  }
+}
+
 }  // namespace
 
 bool CanRouteToNativeMojoEngine(const std::string& engine_id) {
@@ -603,6 +629,9 @@
 
   ime::mojom::InputMethodSettingsPtr settings =
       CreateSettingsFromPrefs(*prefs_, engine_id);
+
+  MigratePinyinAndZhuyinSettings(prefs_, engine_id);
+
   connection_factory_->ConnectToInputMethod(
       engine_id, input_method_.BindNewEndpointAndPassReceiver(),
       std::move(input_method_host), std::move(settings),
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_unittest.cc b/chrome/browser/ash/input_method/native_input_method_engine_unittest.cc
index 4886d75..02da8001 100644
--- a/chrome/browser/ash/input_method/native_input_method_engine_unittest.cc
+++ b/chrome/browser/ash/input_method/native_input_method_engine_unittest.cc
@@ -133,7 +133,10 @@
 
 void SetPinyinLayoutPrefs(Profile& profile, const std::string& layout) {
   base::Value input_method_setting(base::Value::Type::DICTIONARY);
+  // TODO(b/175085612): Remove pinyin.xkbLayout once we migrated from the
+  // legacy pref keys.
   input_method_setting.SetStringPath("pinyin.xkbLayout", layout);
+  input_method_setting.SetStringPath("zh-t-i0-pinyin.xkbLayout", layout);
   profile.GetPrefs()->Set(::prefs::kLanguageInputMethodSpecificSettings,
                           input_method_setting);
 }
diff --git a/chrome/browser/ash/usb/DIR_METADATA b/chrome/browser/ash/usb/DIR_METADATA
index f461eb4..06e627f 100644
--- a/chrome/browser/ash/usb/DIR_METADATA
+++ b/chrome/browser/ash/usb/DIR_METADATA
@@ -1,3 +1 @@
-monorail: {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/back_press/android/BUILD.gn b/chrome/browser/back_press/android/BUILD.gn
index d4aa06e..e79a1aa 100644
--- a/chrome/browser/back_press/android/BUILD.gn
+++ b/chrome/browser/back_press/android/BUILD.gn
@@ -23,12 +23,9 @@
   ]
 }
 
-java_library("junit") {
+robolectric_library("junit") {
   testonly = true
 
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
-
   sources = [ "java/src/org/chromium/chrome/browser/back_press/BackPressManagerUnitTest.java" ]
 
   deps = [
diff --git a/chrome/browser/bluetooth/android/BUILD.gn b/chrome/browser/bluetooth/android/BUILD.gn
index aaf1c63..4036a80 100644
--- a/chrome/browser/bluetooth/android/BUILD.gn
+++ b/chrome/browser/bluetooth/android/BUILD.gn
@@ -42,12 +42,9 @@
       [ "java/src/org/chromium/chrome/browser/bluetooth/BluetoothBridge.java" ]
 }
 
-android_library("junit") {
+robolectric_library("junit") {
   testonly = true
 
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
-
   sources = [ "junit/src/org/chromium/chrome/browser/bluetooth/BluetoothNotificationManagerTest.java" ]
 
   deps = [
diff --git a/chrome/browser/browser_controls/android/BUILD.gn b/chrome/browser/browser_controls/android/BUILD.gn
index a5be491..3e7b0cd 100644
--- a/chrome/browser/browser_controls/android/BUILD.gn
+++ b/chrome/browser/browser_controls/android/BUILD.gn
@@ -25,9 +25,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "java/src/org/chromium/chrome/browser/browser_controls/BrowserStateBrowserControlsVisibilityDelegateTest.java" ]
   deps = [
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 193663e..586fb99 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -134,7 +134,6 @@
       <include name="IDR_USB_DEVICE_MANAGER_CLIENT_MOJOM_WEBUI_JS" file="${root_gen_dir}\mojom-webui\services\device\public\mojom\usb_manager_client.mojom-webui.js" use_base_dir="false" type="BINDATA" />
       <include name="IDR_USB_DEVICE_MANAGER_MOJOM_WEBUI_JS" file="${root_gen_dir}\mojom-webui\services\device\public\mojom\usb_manager.mojom-webui.js" use_base_dir="false" type="BINDATA" />
       <include name="IDR_USB_DEVICE_MANAGER_TEST_MOJOM_WEBUI_JS" file="${root_gen_dir}\mojom-webui\services\device\public\mojom\usb_manager_test.mojom-webui.js" use_base_dir="false" type="BINDATA" />
-      <include name="IDR_USB_DEVICE_MOJOM_WEBUI_JS" file="${root_gen_dir}\mojom-webui\services\device\public\mojom\usb_device.mojom-webui.js" use_base_dir="false" type="BINDATA" />
       <include name="IDR_WEBSTORE_MANIFEST" file="resources\webstore_app\manifest.json" type="BINDATA" />
       <include name="IDR_CRYPTOTOKEN_MANIFEST" file="resources\cryptotoken\manifest.json" type="BINDATA" />
       <if expr="chromeos_ash or chromeos_lacros">
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 049fe06..1656937 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -212,6 +212,7 @@
     "//chrome/browser/browsing_data:constants",
     "//chrome/browser/devtools",
     "//chrome/browser/extensions",
+    "//chrome/browser/favicon",
     "//chrome/browser/image_decoder",
     "//chrome/browser/metrics/structured",
     "//chrome/browser/nearby_sharing/common",
diff --git a/chrome/browser/commerce/merchant_viewer/android/BUILD.gn b/chrome/browser/commerce/merchant_viewer/android/BUILD.gn
index f7e692e..7871eb2 100644
--- a/chrome/browser/commerce/merchant_viewer/android/BUILD.gn
+++ b/chrome/browser/commerce/merchant_viewer/android/BUILD.gn
@@ -82,10 +82,7 @@
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
-
+robolectric_library("junit") {
   testonly = true
 
   sources = [
@@ -136,7 +133,6 @@
     "//content/public/android:content_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_deps:protobuf_lite_runtime_java",
-    "//third_party/android_deps:robolectric_all_java",
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/hamcrest:hamcrest_core_java",
     "//third_party/junit",
diff --git a/chrome/browser/continuous_search/BUILD.gn b/chrome/browser/continuous_search/BUILD.gn
index 421d9420..dd573c4 100644
--- a/chrome/browser/continuous_search/BUILD.gn
+++ b/chrome/browser/continuous_search/BUILD.gn
@@ -156,8 +156,7 @@
     ]
   }
 
-  android_library("junit") {
-    bypass_platform_checks = true
+  robolectric_library("junit") {
     testonly = true
 
     sources = [
diff --git a/chrome/browser/continuous_search/internal/BUILD.gn b/chrome/browser/continuous_search/internal/BUILD.gn
index 43a7fc7..9f71a30 100644
--- a/chrome/browser/continuous_search/internal/BUILD.gn
+++ b/chrome/browser/continuous_search/internal/BUILD.gn
@@ -46,8 +46,7 @@
   resources_package = "org.chromium.chrome.browser.continuous_search"
 }
 
-android_library("junit") {
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   sources = [
diff --git a/chrome/browser/device/BUILD.gn b/chrome/browser/device/BUILD.gn
index 18decde4..9717bb1 100644
--- a/chrome/browser/device/BUILD.gn
+++ b/chrome/browser/device/BUILD.gn
@@ -20,9 +20,7 @@
   ]
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "android/java/src/org/chromium/chrome/browser/device/DeviceConditionsTest.java",
diff --git a/chrome/browser/download/android/BUILD.gn b/chrome/browser/download/android/BUILD.gn
index 82bb9b88..95733a9c 100644
--- a/chrome/browser/download/android/BUILD.gn
+++ b/chrome/browser/download/android/BUILD.gn
@@ -189,9 +189,7 @@
   ]
 }
 
-android_library("junit_tests") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("junit_tests") {
   testonly = true
 
   sources = [
diff --git a/chrome/browser/download/bubble/download_bubble_controller.cc b/chrome/browser/download/bubble/download_bubble_controller.cc
index 98f1367..19e43b9 100644
--- a/chrome/browser/download/bubble/download_bubble_controller.cc
+++ b/chrome/browser/download/bubble/download_bubble_controller.cc
@@ -10,6 +10,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_index/content_index_provider_impl.h"
+#include "chrome/browser/download/bubble/download_display_controller.h"
 #include "chrome/browser/download/download_item_model.h"
 #include "chrome/browser/download/offline_item_model_manager.h"
 #include "chrome/browser/download/offline_item_model_manager_factory.h"
@@ -408,6 +409,10 @@
     case DownloadCommands::DISCARD:
       ProcessDownloadWarningButtonPress(model, command);
       break;
+    case DownloadCommands::REVIEW:
+      model->ReviewScanningVerdict(
+          browser_->tab_strip_model()->GetActiveWebContents());
+      break;
     case DownloadCommands::CANCEL:
       RemoveContentIdFromPartialView(model->GetContentId());
       [[fallthrough]];
diff --git a/chrome/browser/download/download_commands.h b/chrome/browser/download/download_commands.h
index 407128f0..76c842a1 100644
--- a/chrome/browser/download/download_commands.h
+++ b/chrome/browser/download/download_commands.h
@@ -35,6 +35,7 @@
     COPY_TO_CLIPBOARD,         // Copy the contents to the clipboard.
     DEEP_SCAN,                 // Send file to Safe Browsing for deep scanning.
     BYPASS_DEEP_SCANNING,      // Bypass the prompt to deep scan.
+    REVIEW,                    // Show enterprise download review dialog.
     MAX
   };
 
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc
index 5f8d1f3..e42c253 100644
--- a/chrome/browser/download/download_item_model.cc
+++ b/chrome/browser/download/download_item_model.cc
@@ -672,6 +672,7 @@
     case DownloadCommands::LEARN_MORE_MIXED_CONTENT:
     case DownloadCommands::DEEP_SCAN:
     case DownloadCommands::BYPASS_DEEP_SCANNING:
+    case DownloadCommands::REVIEW:
       return DownloadUIModel::IsCommandEnabled(download_commands, command);
   }
   NOTREACHED();
@@ -711,6 +712,7 @@
     case DownloadCommands::COPY_TO_CLIPBOARD:
     case DownloadCommands::DEEP_SCAN:
     case DownloadCommands::BYPASS_DEEP_SCANNING:
+    case DownloadCommands::REVIEW:
       return false;
   }
   return false;
@@ -826,6 +828,7 @@
     case DownloadCommands::PAUSE:
     case DownloadCommands::RESUME:
     case DownloadCommands::COPY_TO_CLIPBOARD:
+    case DownloadCommands::REVIEW:
       DownloadUIModel::ExecuteCommand(download_commands, command);
       break;
     case DownloadCommands::DEEP_SCAN:
diff --git a/chrome/browser/download/download_shelf_context_menu.cc b/chrome/browser/download/download_shelf_context_menu.cc
index f4ce555c2..4f730331 100644
--- a/chrome/browser/download/download_shelf_context_menu.cc
+++ b/chrome/browser/download/download_shelf_context_menu.cc
@@ -51,8 +51,7 @@
     return;
   }
 
-  for (int command_int = 1;
-       command_int < DownloadCommands::Command::BYPASS_DEEP_SCANNING;
+  for (int command_int = 1; command_int < DownloadCommands::Command::REVIEW;
        command_int++) {
     if (model->GetIndexOfCommandId(command_int) != -1 &&
         IsCommandIdEnabled(command_int)) {
@@ -206,6 +205,9 @@
     case DownloadCommands::BYPASS_DEEP_SCANNING:
       id = IDS_OPEN_DOWNLOAD_NOW;
       break;
+    case DownloadCommands::REVIEW:
+      id = IDS_REVIEW_DOWNLOAD;
+      break;
     case DownloadCommands::MAX:
       NOTREACHED();
       break;
diff --git a/chrome/browser/download/download_stats.cc b/chrome/browser/download/download_stats.cc
index d39eb05d..8b658b2 100644
--- a/chrome/browser/download/download_stats.cc
+++ b/chrome/browser/download/download_stats.cc
@@ -165,5 +165,8 @@
       return clicked
                  ? DownloadShelfContextMenuAction::kBypassDeepScanningClicked
                  : DownloadShelfContextMenuAction::kBypassDeepScanningEnabled;
+    case DownloadCommands::Command::REVIEW:
+      return clicked ? DownloadShelfContextMenuAction::kReviewClicked
+                     : DownloadShelfContextMenuAction::kReviewEnabled;
   }
 }
diff --git a/chrome/browser/download/download_stats.h b/chrome/browser/download/download_stats.h
index 8b1d388..272a7dd 100644
--- a/chrome/browser/download/download_stats.h
+++ b/chrome/browser/download/download_stats.h
@@ -221,7 +221,9 @@
   kDeepScanClicked = 31,
   kBypassDeepScanningEnabled = 32,
   kBypassDeepScanningClicked = 33,
-  kMaxValue = kBypassDeepScanningClicked
+  kReviewEnabled = 34,
+  kReviewClicked = 35,
+  kMaxValue = kReviewClicked
 };
 
 DownloadShelfContextMenuAction DownloadCommandToShelfAction(
diff --git a/chrome/browser/download/download_ui_model.cc b/chrome/browser/download/download_ui_model.cc
index d7115de..3faed886 100644
--- a/chrome/browser/download/download_ui_model.cc
+++ b/chrome/browser/download/download_ui_model.cc
@@ -582,6 +582,7 @@
     case DownloadCommands::LEARN_MORE_MIXED_CONTENT:
     case DownloadCommands::DEEP_SCAN:
     case DownloadCommands::BYPASS_DEEP_SCANNING:
+    case DownloadCommands::REVIEW:
       return true;
   }
   NOTREACHED();
@@ -611,6 +612,7 @@
     case DownloadCommands::COPY_TO_CLIPBOARD:
     case DownloadCommands::DEEP_SCAN:
     case DownloadCommands::BYPASS_DEEP_SCANNING:
+    case DownloadCommands::REVIEW:
       return false;
   }
   return false;
@@ -662,6 +664,7 @@
     case DownloadCommands::DEEP_SCAN:
       break;
     case DownloadCommands::BYPASS_DEEP_SCANNING:
+    case DownloadCommands::REVIEW:
       break;
   }
 }
@@ -729,11 +732,20 @@
                  l10n_util::GetStringUTF16(
                      IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_TOO_BIG))
           .AddIconAndColor(views::kInfoIcon, ui::kColorAlertHighSeverity);
-    case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK:
-      return DownloadUIModel::BubbleUIInfo(
-                 l10n_util::GetStringUTF16(
-                     IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_SENSITIVE_CONTENT_BLOCK))
-          .AddIconAndColor(views::kInfoIcon, ui::kColorAlertHighSeverity);
+    case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK: {
+      if (enterprise_connectors::ShouldPromptReviewForDownload(
+              profile(), GetDangerType())) {
+        return DownloadUIModel::BubbleUIInfo(/*has_progress_bar=*/false)
+            .AddIconAndColor(vector_icons::kNotSecureWarningIcon,
+                             ui::kColorAlertHighSeverity)
+            .AddPrimaryButton(DownloadCommands::Command::REVIEW);
+      } else {
+        return DownloadUIModel::BubbleUIInfo(
+                   l10n_util::GetStringUTF16(
+                       IDS_DOWNLOAD_BUBBLE_SUBPAGE_SUMMARY_SENSITIVE_CONTENT_BLOCK))
+            .AddIconAndColor(views::kInfoIcon, ui::kColorAlertHighSeverity);
+      }
+    }
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
@@ -845,6 +857,28 @@
       break;
   }
 
+  if (enterprise_connectors::ShouldPromptReviewForDownload(profile(),
+                                                           GetDangerType())) {
+    switch (GetDangerType()) {
+      case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
+        return DownloadUIModel::BubbleUIInfo(/*has_progress_bar=*/false)
+            .AddIconAndColor(vector_icons::kNotSecureWarningIcon,
+                             ui::kColorAlertHighSeverity)
+            .AddPrimaryButton(DownloadCommands::Command::REVIEW);
+      case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+        return DownloadUIModel::BubbleUIInfo(/*has_progress_bar=*/false)
+            .AddIconAndColor(vector_icons::kNotSecureWarningIcon,
+                             ui::kColorAlertMediumSeverity)
+            .AddPrimaryButton(DownloadCommands::Command::REVIEW);
+      case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING:
+        return DownloadUIModel::BubbleUIInfo(/*has_progress_bar=*/false)
+            .AddIconAndColor(views::kInfoIcon, ui::kColorAlertMediumSeverity)
+            .AddPrimaryButton(DownloadCommands::Command::REVIEW);
+      default:
+        break;
+    }
+  }
+
   switch (GetDangerType()) {
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
       if (IsExtensionDownload()) {
diff --git a/chrome/browser/download/internal/android/BUILD.gn b/chrome/browser/download/internal/android/BUILD.gn
index 22e0930..e6a8654 100644
--- a/chrome/browser/download/internal/android/BUILD.gn
+++ b/chrome/browser/download/internal/android/BUILD.gn
@@ -267,9 +267,7 @@
   resources_package = "org.chromium.chrome.browser.download.internal"
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/chrome/browser/download/home/filter/DeleteUndoOfflineItemFilterTest.java",
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc
index 52a4fdb0..0398fb2 100644
--- a/chrome/browser/download/notification/download_item_notification.cc
+++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -199,6 +199,10 @@
       base::RecordAction(
           UserMetricsAction("DownloadNotification.Button_BypassDeepScanning"));
       break;
+    case DownloadCommands::REVIEW:
+      base::RecordAction(
+          UserMetricsAction("DownloadNotification.Button_Review"));
+      break;
     case DownloadCommands::MAX:
       NOTREACHED();
       break;
@@ -902,6 +906,7 @@
     case DownloadCommands::PLATFORM_OPEN:
     case DownloadCommands::LEARN_MORE_INTERRUPTED:
     case DownloadCommands::BYPASS_DEEP_SCANNING:
+    case DownloadCommands::REVIEW:
     case DownloadCommands::MAX:
       // Only for menu.
       NOTREACHED();
diff --git a/chrome/browser/download/offline_item_model.cc b/chrome/browser/download/offline_item_model.cc
index c7780dc..bacad682 100644
--- a/chrome/browser/download/offline_item_model.cc
+++ b/chrome/browser/download/offline_item_model.cc
@@ -10,6 +10,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "chrome/browser/download/download_commands.h"
 #include "chrome/browser/download/offline_item_model_manager.h"
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -308,6 +309,7 @@
     case DownloadCommands::LEARN_MORE_MIXED_CONTENT:
     case DownloadCommands::DEEP_SCAN:
     case DownloadCommands::BYPASS_DEEP_SCANNING:
+    case DownloadCommands::REVIEW:
       return DownloadUIModel::IsCommandEnabled(download_commands, command);
   }
   NOTREACHED();
@@ -339,6 +341,7 @@
     case DownloadCommands::COPY_TO_CLIPBOARD:
     case DownloadCommands::DEEP_SCAN:
     case DownloadCommands::BYPASS_DEEP_SCANNING:
+    case DownloadCommands::REVIEW:
       return false;
   }
   return false;
@@ -367,6 +370,7 @@
     case DownloadCommands::COPY_TO_CLIPBOARD:
     case DownloadCommands::DEEP_SCAN:
     case DownloadCommands::BYPASS_DEEP_SCANNING:
+    case DownloadCommands::REVIEW:
       DownloadUIModel::ExecuteCommand(download_commands, command);
       break;
   }
diff --git a/chrome/browser/enterprise/util/BUILD.gn b/chrome/browser/enterprise/util/BUILD.gn
index 489a22e..55b0d2d 100644
--- a/chrome/browser/enterprise/util/BUILD.gn
+++ b/chrome/browser/enterprise/util/BUILD.gn
@@ -28,9 +28,7 @@
   sources = _jni_sources
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   sources = [ "android/java/src/org/chromium/chrome/browser/enterprise/util/EnterpriseInfoImplTest.java" ]
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 2d0ab9d..1d91c6a 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -773,6 +773,7 @@
     "//chrome/browser:theme_properties",
     "//chrome/browser/browsing_data:constants",
     "//chrome/browser/devtools",
+    "//chrome/browser/favicon",
     "//chrome/browser/first_party_sets",
     "//chrome/browser/image_decoder",
     "//chrome/browser/media/router",
diff --git a/chrome/browser/extensions/api/favicon/favicon_util_unittest.cc b/chrome/browser/extensions/api/favicon/favicon_util_unittest.cc
index 5c19285..f92639f 100644
--- a/chrome/browser/extensions/api/favicon/favicon_util_unittest.cc
+++ b/chrome/browser/extensions/api/favicon/favicon_util_unittest.cc
@@ -22,12 +22,12 @@
       {false, "chrome-extension://id/_favicon"},
       {false, "chrome-extension://id/_favicon/"},
       {false, "chrome-extension://id/_favicon/?"},
-      {true, "chrome-extension://id/_favicon?page_url=https://ok.com"},
-      {true, "chrome-extension://id/_favicon/?page_url=https://ok.com"},
-      {true, "chrome-extension://id/_favicon/?page_url=https://ok.com&size=16"},
+      {true, "chrome-extension://id/_favicon?pageUrl=https://ok.com"},
+      {true, "chrome-extension://id/_favicon/?pageUrl=https://ok.com"},
+      {true, "chrome-extension://id/_favicon/?pageUrl=https://ok.com&size=16"},
       {true,
-       "chrome-extension://id/_favicon/?page_url=https://"
-       "ok.com&size=16&scale_factor=1.0x&server_fallback=1"}};
+       "chrome-extension://id/_favicon/?pageUrl=https://"
+       "ok.com&size=16&scaleFactor=1.0x&server_fallback=1"}};
   for (const auto& test_case : test_cases) {
     GURL url(test_case.url);
     chrome::ParsedFaviconPath parsed;
diff --git a/chrome/browser/extensions/api/terminal/DIR_METADATA b/chrome/browser/extensions/api/terminal/DIR_METADATA
index b3cd940..06e627f 100644
--- a/chrome/browser/extensions/api/terminal/DIR_METADATA
+++ b/chrome/browser/extensions/api/terminal/DIR_METADATA
@@ -1,3 +1 @@
-monorail {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/favicon/BUILD.gn b/chrome/browser/favicon/BUILD.gn
new file mode 100644
index 0000000..fe53f87
--- /dev/null
+++ b/chrome/browser/favicon/BUILD.gn
@@ -0,0 +1,35 @@
+# 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.
+
+source_set("favicon") {
+  sources = [
+    "chrome_favicon_client.cc",
+    "chrome_favicon_client.h",
+    "favicon_service_factory.cc",
+    "favicon_service_factory.h",
+    "favicon_utils.cc",
+    "favicon_utils.h",
+    "history_ui_favicon_request_handler_factory.cc",
+    "history_ui_favicon_request_handler_factory.h",
+    "large_icon_service_factory.cc",
+    "large_icon_service_factory.h",
+  ]
+  deps = [
+    "//chrome/app/resources:platform_locale_settings",
+    "//chrome/browser/profiles",
+    "//chrome/browser/profiles:profile",
+    "//chrome/common",
+    "//components/bookmarks/browser",
+    "//components/favicon/content",
+    "//components/favicon/core",
+    "//components/favicon/core:history_implementation",
+    "//components/image_fetcher/core",
+    "//components/keyed_service/content",
+    "//components/sync",
+    "//content/public/browser",
+    "//ui/gfx",
+    "//ui/native_theme",
+    "//ui/resources",
+  ]
+}
diff --git a/chrome/browser/feed/android/BUILD.gn b/chrome/browser/feed/android/BUILD.gn
index 209bca4..69188fc 100644
--- a/chrome/browser/feed/android/BUILD.gn
+++ b/chrome/browser/feed/android/BUILD.gn
@@ -275,12 +275,9 @@
   ]
 }
 
-android_library("junit") {
+robolectric_library("junit") {
   testonly = true
 
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
-
   sources = [
     "java/src/org/chromium/chrome/browser/feed/FakeLinearLayoutManager.java",
     "java/src/org/chromium/chrome/browser/feed/FeedFeaturesTest.java",
diff --git a/chrome/browser/feed/android/java/res/layout/new_tab_page_multi_feed_header.xml b/chrome/browser/feed/android/java/res/layout/new_tab_page_multi_feed_header.xml
index e403e46a..21086a1 100644
--- a/chrome/browser/feed/android/java/res/layout/new_tab_page_multi_feed_header.xml
+++ b/chrome/browser/feed/android/java/res/layout/new_tab_page_multi_feed_header.xml
@@ -30,7 +30,7 @@
 
     <!-- Null content description for now because UX in flux. -->
     <ImageView
-        android:id="@+id/status_indicator"
+        android:id="@+id/section_status_indicator"
         android:layout_width="@dimen/feed_header_icon_size"
         android:layout_height="@dimen/feed_header_icon_size"
         android:src="@drawable/ic_visibility_off_black"
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/sections/SectionHeaderView.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/sections/SectionHeaderView.java
index 7f5e1fe8..7340984f 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/sections/SectionHeaderView.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/sections/SectionHeaderView.java
@@ -168,7 +168,7 @@
 
         mTitleView = findViewById(R.id.header_title);
         mMenuView = findViewById(R.id.header_menu);
-        mLeadingStatusIndicator = findViewById(R.id.status_indicator);
+        mLeadingStatusIndicator = findViewById(R.id.section_status_indicator);
         mTabLayout = findViewById(R.id.tab_list_view);
         mContent = findViewById(R.id.main_content);
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index c3dba11..9cff2690 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -405,6 +405,11 @@
     "expiry_milestone": 106
   },
   {
+    "name": "autofill-enable-get-details-for-enroll-parsing-in-upload-card-response",
+    "owners": [ "vinnypersky@google.com", "siyua" ],
+    "expiry_milestone": 110
+  },
+  {
     "name": "autofill-enable-manual-fallback-for-virtual-cards",
     "owners": [ "siashah", "siyua" ],
     "expiry_milestone": 106
@@ -959,11 +964,6 @@
     "expiry_milestone": 104
   },
   {
-    "name": "contextual-search-new-settings",
-    "owners": [ "//chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/OWNERS", "contextual-search-eng@google.com" ],
-    "expiry_milestone": 104
-  },
-  {
     "name": "contextual-search-translations",
     "owners": [ "//chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/OWNERS", "contextual-search-eng@google.com" ],
     "expiry_milestone": 104
@@ -1327,7 +1327,7 @@
   {
     "name": "dns-proxy-enable-doh",
     "owners": [ "garrick", "jasongustaman" ],
-    "expiry_milestone": 104
+    "expiry_milestone": 109
   },
    {
     "name": "document-transition",
@@ -1999,7 +1999,7 @@
   {
     "name": "enable-dns-proxy",
     "owners": [ "garrick", "jasongustaman", "cros-networking@google.com" ],
-    "expiry_milestone": 104
+    "expiry_milestone": 109
   },
   {
     "name": "enable-docked-magnifier-resizing",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 3a6753b..e1e225a 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -319,6 +319,17 @@
     "Controls if different width limits are used for the popup that provides "
     "Autofill suggestions, depending on the type of data that is filled.";
 
+const char kAutofillEnableGetDetailsForEnrollParsingInUploadCardResponseName[] =
+    "Enable parsing of the GetDetailsForEnrollResponseDetails in the "
+    "UploadCardResponseDetails";
+const char
+    kAutofillEnableGetDetailsForEnrollParsingInUploadCardResponseDescription[] =
+        "When enabled, the GetDetailsForEnrollResponseDetails in the "
+        "UploadCardResponseDetails will be parsed, which will allow the "
+        "Virtual Card Enrollment flow to skip making a new GetDetailsForEnroll "
+        "request. This is an optimization to improve the latency of the "
+        "Virtual Card Enrollment flow.";
+
 const char kAutofillEnableManualFallbackForVirtualCardsName[] =
     "Show manual fallback for virtual cards";
 const char kAutofillEnableManualFallbackForVirtualCardsDescription[] =
@@ -3175,12 +3186,6 @@
 const char kContextualSearchForceCaptionDescription[] =
     "Forces a caption to always be shown in the Touch to Search Bar.";
 
-const char KContextualSearchNewSettingsName[] =
-    "Contextual Search new settings";
-const char KContextualSearchNewSettingsDescription[] =
-    "Adds a toggle to Settings page to specifically control Contextual Search "
-    "opt-in state, and update Opt-in messages.";
-
 const char kContextualSearchTranslationsName[] =
     "Contextual Search translations";
 const char kContextualSearchTranslationsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index cee417a..d3e3ac5 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -188,6 +188,11 @@
 extern const char kAutofillTypeSpecificPopupWidthName[];
 extern const char kAutofillTypeSpecificPopupWidthDescription[];
 
+extern const char
+    kAutofillEnableGetDetailsForEnrollParsingInUploadCardResponseName[];
+extern const char
+    kAutofillEnableGetDetailsForEnrollParsingInUploadCardResponseDescription[];
+
 extern const char kAutofillEnableManualFallbackForVirtualCardsName[];
 extern const char kAutofillEnableManualFallbackForVirtualCardsDescription[];
 
@@ -1794,9 +1799,6 @@
 extern const char kContextualSearchForceCaptionName[];
 extern const char kContextualSearchForceCaptionDescription[];
 
-extern const char KContextualSearchNewSettingsName[];
-extern const char KContextualSearchNewSettingsDescription[];
-
 extern const char kContextualSearchTranslationsName[];
 extern const char kContextualSearchTranslationsDescription[];
 
diff --git a/chrome/browser/flags/BUILD.gn b/chrome/browser/flags/BUILD.gn
index f0158f63..63f1495 100644
--- a/chrome/browser/flags/BUILD.gn
+++ b/chrome/browser/flags/BUILD.gn
@@ -70,9 +70,7 @@
   sources = [ "android/chrome_session_state.h" ]
 }
 
-java_library("flags_junit_tests") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("flags_junit_tests") {
   testonly = true
   sources = [
     "android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsAnnotationUnitTest.java",
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index b9418eb..6bd8528d 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -212,7 +212,6 @@
     &kContextualSearchDelayedIntelligence,
     &kContextualSearchForceCaption,
     &kContextualSearchMlTapSuppression,
-    &KContextualSearchNewSettings,
     &kContextualSearchTapDisableOverride,
     &kContextualSearchThinWebViewImplementation,
     &kContextualSearchTranslations,
@@ -592,9 +591,6 @@
 const base::Feature kContextualSearchMlTapSuppression{
     "ContextualSearchMlTapSuppression", base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature KContextualSearchNewSettings{
-    "ContextualSearchNewSettings", base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kContextualSearchTapDisableOverride{
     "ContextualSearchTapDisableOverride", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index b81132e..5fe378d 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -71,7 +71,6 @@
 extern const base::Feature kContextualSearchDelayedIntelligence;
 extern const base::Feature kContextualSearchForceCaption;
 extern const base::Feature kContextualSearchMlTapSuppression;
-extern const base::Feature KContextualSearchNewSettings;
 extern const base::Feature kContextualSearchTapDisableOverride;
 extern const base::Feature kContextualSearchThinWebViewImplementation;
 extern const base::Feature kContextualSearchTranslations;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index 90de114..b5bd8dd35 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -297,7 +297,6 @@
     public static final String CONTEXTUAL_SEARCH_FORCE_CAPTION = "ContextualSearchForceCaption";
     public static final String CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION =
             "ContextualSearchMlTapSuppression";
-    public static final String CONTEXTUAL_SEARCH_NEW_SETTINGS = "ContextualSearchNewSettings";
     public static final String CONTEXTUAL_SEARCH_TAP_DISABLE_OVERRIDE =
             "ContextualSearchTapDisableOverride";
     public static final String CONTEXTUAL_SEARCH_THIN_WEB_VIEW_IMPLEMENTATION =
diff --git a/chrome/browser/incognito/BUILD.gn b/chrome/browser/incognito/BUILD.gn
index 9dc80a3..d8409525 100644
--- a/chrome/browser/incognito/BUILD.gn
+++ b/chrome/browser/incognito/BUILD.gn
@@ -106,12 +106,9 @@
   ]
 }
 
-android_library("incognito_junit_tests") {
+robolectric_library("incognito_junit_tests") {
   testonly = true
 
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
-
   sources = [
     "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthControllerTest.java",
     "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthManagerTest.java",
diff --git a/chrome/browser/loading_modal/android/BUILD.gn b/chrome/browser/loading_modal/android/BUILD.gn
index 5377ee4..bd11b6f3 100644
--- a/chrome/browser/loading_modal/android/BUILD.gn
+++ b/chrome/browser/loading_modal/android/BUILD.gn
@@ -31,9 +31,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   sources = [ "junit/src/org/chromium/chrome/browser/loading_modal/LoadingModalDialogMediatorTest.java" ]
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc
index 122c7aa..2df5ce6 100644
--- a/chrome/browser/net/profile_network_context_service.cc
+++ b/chrome/browser/net/profile_network_context_service.cc
@@ -69,6 +69,10 @@
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "third_party/blink/public/common/features.h"
 
+#if BUILDFLAG(IS_ANDROID)
+#include "base/android/remove_stale_data.h"
+#endif
+
 #if BUILDFLAG(IS_CHROMEOS)
 #include "chrome/browser/certificate_provider/certificate_provider.h"
 #include "chrome/browser/certificate_provider/certificate_provider_service.h"
@@ -707,6 +711,9 @@
     network::mojom::NetworkContextParams* network_context_params,
     cert_verifier::mojom::CertVerifierCreationParams*
         cert_verifier_creation_params) {
+  TRACE_EVENT0(
+      "startup",
+      "ProfileNetworkContextService::ConfigureNetworkContextParamsInternal");
   if (profile_->IsOffTheRecord())
     in_memory = true;
   base::FilePath path(GetPartitionPath(relative_partition_path));
@@ -767,6 +774,17 @@
     network_context_params->file_paths->unsandboxed_data_path = path;
     network_context_params->file_paths->trigger_migration =
         base::FeatureList::IsEnabled(features::kTriggerNetworkDataMigration);
+
+#if BUILDFLAG(IS_ANDROID)
+    // On Android the `data_directory` was used by some wrong builds instead of
+    // `unsandboxed_data_path`. Cleaning it up. See crbug.com/1331809.
+    // The `trigger_migration` has always been false and will remain to be such
+    // on Android, hence not checking for it.
+    DCHECK(!network_context_params->file_paths->trigger_migration);
+    base::android::RemoveStaleDataDirectory(
+        network_context_params->file_paths->data_directory.path());
+#endif  // BUILDFLAG(IS_ANDROID)
+
     // Currently this just contains HttpServerProperties, but that will likely
     // change.
     network_context_params->file_paths->http_server_properties_file_name =
diff --git a/chrome/browser/notifications/BUILD.gn b/chrome/browser/notifications/BUILD.gn
index a197e83..dc8457ee 100644
--- a/chrome/browser/notifications/BUILD.gn
+++ b/chrome/browser/notifications/BUILD.gn
@@ -99,9 +99,7 @@
     ]
   }
 
-  android_library("junit_tests") {
-    # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-    bypass_platform_checks = true
+  robolectric_library("junit_tests") {
     testonly = true
 
     sources = [
diff --git a/chrome/browser/page_annotations/test/android/BUILD.gn b/chrome/browser/page_annotations/test/android/BUILD.gn
index d00dd7e..8c9f0a4 100644
--- a/chrome/browser/page_annotations/test/android/BUILD.gn
+++ b/chrome/browser/page_annotations/test/android/BUILD.gn
@@ -5,10 +5,7 @@
 import("//build/config/android/config.gni")
 import("//build/config/android/rules.gni")
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
-
+robolectric_library("junit") {
   testonly = true
 
   sources = [
diff --git a/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtilsUnitTest.java b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtilsUnitTest.java
index 22e27eb..b9429b1a 100644
--- a/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtilsUnitTest.java
+++ b/chrome/browser/page_annotations/test/android/java/src/org/chromium/chrome/browser/page_annotations/PageAnnotationUtilsUnitTest.java
@@ -13,7 +13,7 @@
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.page_annotations.PageAnnotation.PageAnnotationType;
 
-import java.util.LinkedList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -22,9 +22,8 @@
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 public class PageAnnotationUtilsUnitTest {
-    private static final List<PageAnnotation> DUMMY_ANNOTATIONS_LIST = new LinkedList<>() {
-        { add(new BuyableProductPageAnnotation(100L, "USD", "200")); }
-    };
+    private static final List<PageAnnotation> DUMMY_ANNOTATIONS_LIST = Arrays.asList(
+            new PageAnnotation[] {new BuyableProductPageAnnotation(100L, "USD", "200")});
 
     private static class DummyPageAnnotation extends PageAnnotation {
         DummyPageAnnotation() {
@@ -67,4 +66,4 @@
                 DUMMY_ANNOTATIONS_LIST, DummyPageAnnotation.class);
         Assert.assertNull(annotation);
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/partnerbookmarks/BUILD.gn b/chrome/browser/partnerbookmarks/BUILD.gn
index ce1e8c2..65c1cde 100644
--- a/chrome/browser/partnerbookmarks/BUILD.gn
+++ b/chrome/browser/partnerbookmarks/BUILD.gn
@@ -49,12 +49,9 @@
   sources = [ "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java" ]
 }
 
-android_library("junit") {
+robolectric_library("junit") {
   testonly = true
 
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
-
   sources = [
     "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java",
     "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java",
diff --git a/chrome/browser/password_edit_dialog/android/BUILD.gn b/chrome/browser/password_edit_dialog/android/BUILD.gn
index 1c0d219c6..8cce0c71 100644
--- a/chrome/browser/password_edit_dialog/android/BUILD.gn
+++ b/chrome/browser/password_edit_dialog/android/BUILD.gn
@@ -68,9 +68,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "java/src/org/chromium/chrome/browser/password_edit_dialog/PasswordEditDialogTest.java" ]
 
diff --git a/chrome/browser/password_entry_edit/android/internal/BUILD.gn b/chrome/browser/password_entry_edit/android/internal/BUILD.gn
index ba6e603..fe7d024 100644
--- a/chrome/browser/password_entry_edit/android/internal/BUILD.gn
+++ b/chrome/browser/password_entry_edit/android/internal/BUILD.gn
@@ -38,9 +38,7 @@
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "java/src/org/chromium/chrome/browser/password_entry_edit/CredentialEditControllerTest.java" ]
 
diff --git a/chrome/browser/payments/android/BUILD.gn b/chrome/browser/payments/android/BUILD.gn
index ede0a7c..2f17496 100644
--- a/chrome/browser/payments/android/BUILD.gn
+++ b/chrome/browser/payments/android/BUILD.gn
@@ -13,9 +13,7 @@
 }
 
 # TODO(crbug.com/1164979): remove the dependency on chrome_java.
-android_library("junit_test_support") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("junit_test_support") {
   testonly = true
   deps = [
     "//chrome/android:chrome_java",
@@ -46,9 +44,7 @@
 }
 
 # TODO(crbug.com/1164979): remove the dependency on chrome_java.
-java_library("junit") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   deps = [
     ":junit_test_support",
diff --git a/chrome/browser/policy/android/BUILD.gn b/chrome/browser/policy/android/BUILD.gn
index cfc46fd8..31836cab 100644
--- a/chrome/browser/policy/android/BUILD.gn
+++ b/chrome/browser/policy/android/BUILD.gn
@@ -67,9 +67,7 @@
   ]
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   sources = [
diff --git a/chrome/browser/preferences/BUILD.gn b/chrome/browser/preferences/BUILD.gn
index ce9bedd8..5657e49 100644
--- a/chrome/browser/preferences/BUILD.gn
+++ b/chrome/browser/preferences/BUILD.gn
@@ -53,9 +53,7 @@
   sources = [ "android/java/src/org/chromium/chrome/browser/preferences/PrefChangeRegistrar.java" ]
 }
 
-java_library("preferences_junit_tests") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("preferences_junit_tests") {
   testonly = true
   sources = [
     "android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeyCheckerTest.java",
diff --git a/chrome/browser/printing/print_backend_service_manager.h b/chrome/browser/printing/print_backend_service_manager.h
index 30a0eb9..7b4d4aa 100644
--- a/chrome/browser/printing/print_backend_service_manager.h
+++ b/chrome/browser/printing/print_backend_service_manager.h
@@ -156,7 +156,7 @@
 
  private:
   friend base::NoDestructor<PrintBackendServiceManager>;
-  friend class PrintBackendPrintBrowserTestBase;
+  friend class SystemAccessProcessPrintBrowserTestBase;
   FRIEND_TEST_ALL_PREFIXES(PrintBackendServiceManagerTest,
                            IsIdleTimeoutUpdateNeededForRegisteredClient);
   FRIEND_TEST_ALL_PREFIXES(PrintBackendServiceManagerTest,
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc
index ef6d61a0..3329681 100644
--- a/chrome/browser/printing/print_browsertest.cc
+++ b/chrome/browser/printing/print_browsertest.cc
@@ -2423,10 +2423,10 @@
 };
 #endif  // BUILDFLAG(ENABLE_OOP_PRINTING)
 
-class PrintBackendPrintBrowserTestBase : public PrintBrowserTest {
+class SystemAccessProcessPrintBrowserTestBase : public PrintBrowserTest {
  public:
-  PrintBackendPrintBrowserTestBase() = default;
-  ~PrintBackendPrintBrowserTestBase() override = default;
+  SystemAccessProcessPrintBrowserTestBase() = default;
+  ~SystemAccessProcessPrintBrowserTestBase() override = default;
 
   virtual bool UseService() = 0;
 
@@ -2445,56 +2445,58 @@
       // Safe to use `base::Unretained(this)` since this testing class
       // necessarily must outlive all interactions from the tests which will
       // run through `TestPrintJobWorkerOop`, the user of these callbacks.
-      test_print_oop_callbacks_.error_check_callback =
-          base::BindRepeating(&PrintBackendPrintBrowserTestBase::ErrorCheck,
-                              base::Unretained(this));
+      test_print_oop_callbacks_.error_check_callback = base::BindRepeating(
+          &SystemAccessProcessPrintBrowserTestBase::ErrorCheck,
+          base::Unretained(this));
       test_print_oop_callbacks_.did_use_default_settings_callback =
           base::BindRepeating(
-              &PrintBackendPrintBrowserTestBase::OnDidUseDefaultSettings,
+              &SystemAccessProcessPrintBrowserTestBase::OnDidUseDefaultSettings,
               base::Unretained(this));
 #if BUILDFLAG(IS_WIN)
       test_print_oop_callbacks_.did_ask_user_for_settings_callback =
           base::BindRepeating(
-              &PrintBackendPrintBrowserTestBase::OnDidAskUserForSettings,
+              &SystemAccessProcessPrintBrowserTestBase::OnDidAskUserForSettings,
               base::Unretained(this));
 #endif
       test_print_oop_callbacks_.did_start_printing_callback =
           base::BindRepeating(
-              &PrintBackendPrintBrowserTestBase::OnDidStartPrinting,
+              &SystemAccessProcessPrintBrowserTestBase::OnDidStartPrinting,
               base::Unretained(this));
 #if BUILDFLAG(IS_WIN)
       test_print_oop_callbacks_.did_render_printed_page_callback =
           base::BindRepeating(
-              &PrintBackendPrintBrowserTestBase::OnDidRenderPrintedPage,
+              &SystemAccessProcessPrintBrowserTestBase::OnDidRenderPrintedPage,
               base::Unretained(this));
 #endif
-      test_print_oop_callbacks_.did_render_printed_document_callback =
-          base::BindRepeating(
-              &PrintBackendPrintBrowserTestBase::OnDidRenderPrintedDocument,
-              base::Unretained(this));
+      test_print_oop_callbacks_
+          .did_render_printed_document_callback = base::BindRepeating(
+          &SystemAccessProcessPrintBrowserTestBase::OnDidRenderPrintedDocument,
+          base::Unretained(this));
       test_print_oop_callbacks_.did_document_done_callback =
           base::BindRepeating(
-              &PrintBackendPrintBrowserTestBase::OnDidDocumentDone,
+              &SystemAccessProcessPrintBrowserTestBase::OnDidDocumentDone,
               base::Unretained(this));
       test_print_oop_callbacks_.did_show_error_dialog = base::BindRepeating(
-          &PrintBackendPrintBrowserTestBase::OnDidShowErrorDialog,
+          &SystemAccessProcessPrintBrowserTestBase::OnDidShowErrorDialog,
           base::Unretained(this));
       test_print_oop_callbacks_.did_stop_callback = base::BindRepeating(
-          &PrintBackendPrintBrowserTestBase::OnDidStop, base::Unretained(this));
+          &SystemAccessProcessPrintBrowserTestBase::OnDidStop,
+          base::Unretained(this));
     } else {
       test_print_callbacks_.did_invoke_use_default_settings_callback =
-          base::BindRepeating(
-              &PrintBackendPrintBrowserTestBase::OnDidInvokeUseDefaultSettings,
-              base::Unretained(this));
+          base::BindRepeating(&SystemAccessProcessPrintBrowserTestBase::
+                                  OnDidInvokeUseDefaultSettings,
+                              base::Unretained(this));
       test_print_callbacks_.did_invoke_get_settings_with_ui_callback =
-          base::BindRepeating(
-              &PrintBackendPrintBrowserTestBase::OnDidInvokeGetSettingsWithUI,
-              base::Unretained(this));
+          base::BindRepeating(&SystemAccessProcessPrintBrowserTestBase::
+                                  OnDidInvokeGetSettingsWithUI,
+                              base::Unretained(this));
       test_print_callbacks_.did_stop_callback = base::BindRepeating(
-          &PrintBackendPrintBrowserTestBase::OnDidStop, base::Unretained(this));
+          &SystemAccessProcessPrintBrowserTestBase::OnDidStop,
+          base::Unretained(this));
     }
     test_create_print_job_worker_callback_ = base::BindRepeating(
-        &PrintBackendPrintBrowserTestBase::CreatePrintJobWorker,
+        &SystemAccessProcessPrintBrowserTestBase::CreatePrintJobWorker,
         base::Unretained(this), UseService());
     PrinterQuery::SetCreatePrintJobWorkerCallbackForTest(
         &test_create_print_job_worker_callback_);
@@ -2903,36 +2905,36 @@
   bool stop_invoked_ = false;
 };
 
-class PrintBackendPrintBrowserTestSandboxedService
-    : public PrintBackendPrintBrowserTestBase {
+class SystemAccessProcessSandboxedServicePrintBrowserTest
+    : public SystemAccessProcessPrintBrowserTestBase {
  public:
-  PrintBackendPrintBrowserTestSandboxedService() = default;
-  ~PrintBackendPrintBrowserTestSandboxedService() override = default;
+  SystemAccessProcessSandboxedServicePrintBrowserTest() = default;
+  ~SystemAccessProcessSandboxedServicePrintBrowserTest() override = default;
 
   bool UseService() override { return true; }
   bool SandboxService() override { return true; }
 };
 
-class PrintBackendPrintBrowserTestService
-    : public PrintBackendPrintBrowserTestBase,
+class SystemAccessProcessServicePrintBrowserTest
+    : public SystemAccessProcessPrintBrowserTestBase,
       public testing::WithParamInterface<bool> {
  public:
-  PrintBackendPrintBrowserTestService() = default;
-  ~PrintBackendPrintBrowserTestService() override = default;
+  SystemAccessProcessServicePrintBrowserTest() = default;
+  ~SystemAccessProcessServicePrintBrowserTest() override = default;
 
   bool UseService() override { return true; }
   bool SandboxService() override { return GetParam(); }
 };
 
 INSTANTIATE_TEST_SUITE_P(All,
-                         PrintBackendPrintBrowserTestService,
+                         SystemAccessProcessServicePrintBrowserTest,
                          testing::Bool());
 
-class PrintBackendPrintBrowserTestInBrowser
-    : public PrintBackendPrintBrowserTestBase {
+class SystemAccessProcessInBrowserPrintBrowserTest
+    : public SystemAccessProcessPrintBrowserTestBase {
  public:
-  PrintBackendPrintBrowserTestInBrowser() = default;
-  ~PrintBackendPrintBrowserTestInBrowser() override = default;
+  SystemAccessProcessInBrowserPrintBrowserTest() = default;
+  ~SystemAccessProcessInBrowserPrintBrowserTest() override = default;
 
   bool UseService() override { return false; }
   bool SandboxService() override { return false; }
@@ -2948,12 +2950,12 @@
   kOopUnsandboxedService,
 };
 
-class PrintBackendPrintBrowserTest
-    : public PrintBackendPrintBrowserTestBase,
+class SystemAccessProcessPrintBrowserTest
+    : public SystemAccessProcessPrintBrowserTestBase,
       public testing::WithParamInterface<PrintBackendFeatureVariation> {
  public:
-  PrintBackendPrintBrowserTest() = default;
-  ~PrintBackendPrintBrowserTest() override = default;
+  SystemAccessProcessPrintBrowserTest() = default;
+  ~SystemAccessProcessPrintBrowserTest() override = default;
 
   bool UseService() override {
     return GetParam() != PrintBackendFeatureVariation::kInBrowserProcess;
@@ -2965,12 +2967,13 @@
 
 INSTANTIATE_TEST_SUITE_P(
     All,
-    PrintBackendPrintBrowserTest,
+    SystemAccessProcessPrintBrowserTest,
     testing::Values(PrintBackendFeatureVariation::kInBrowserProcess,
                     PrintBackendFeatureVariation::kOopSandboxedService,
                     PrintBackendFeatureVariation::kOopUnsandboxedService));
 
-IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTest, UpdatePrintSettings) {
+IN_PROC_BROWSER_TEST_P(SystemAccessProcessPrintBrowserTest,
+                       UpdatePrintSettings) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
 
@@ -3018,7 +3021,8 @@
 
 #if BUILDFLAG(ENABLE_OOP_PRINTING)
 
-IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService, StartPrinting) {
+IN_PROC_BROWSER_TEST_P(SystemAccessProcessServicePrintBrowserTest,
+                       StartPrinting) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
 
@@ -3053,7 +3057,7 @@
 
 // TODO(crbug.com/1326580):  Enable once multipage printing doesn't get stuck
 // because of insufficient rendered preview pages due to forced N-up.
-IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_P(SystemAccessProcessServicePrintBrowserTest,
                        DISABLED_StartPrintingMultipage) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3094,7 +3098,7 @@
   EXPECT_TRUE(stop_invoked());
 }
 
-IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_P(SystemAccessProcessServicePrintBrowserTest,
                        StartPrintingSpoolingSharedMemoryError) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3125,7 +3129,7 @@
   EXPECT_TRUE(stop_invoked());
 }
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestSandboxedService,
+IN_PROC_BROWSER_TEST_F(SystemAccessProcessSandboxedServicePrintBrowserTest,
                        StartPrintingAccessDenied) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3162,7 +3166,7 @@
   EXPECT_TRUE(stop_invoked());
 }
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestSandboxedService,
+IN_PROC_BROWSER_TEST_F(SystemAccessProcessSandboxedServicePrintBrowserTest,
                        StartPrintingRepeatedAccessDenied) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3193,7 +3197,7 @@
 }
 
 #if BUILDFLAG(IS_WIN)
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestSandboxedService,
+IN_PROC_BROWSER_TEST_F(SystemAccessProcessSandboxedServicePrintBrowserTest,
                        StartPrintingRenderPageAccessDenied) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3228,7 +3232,7 @@
 
 // TODO(crbug.com/1008222)  Include Windows once XPS print pipeline is added.
 #if !BUILDFLAG(IS_WIN)
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestSandboxedService,
+IN_PROC_BROWSER_TEST_F(SystemAccessProcessSandboxedServicePrintBrowserTest,
                        StartPrintingRenderDocumentAccessDenied) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3260,7 +3264,7 @@
 }
 #endif  // !BUILDFLAG(IS_WIN)
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestSandboxedService,
+IN_PROC_BROWSER_TEST_F(SystemAccessProcessSandboxedServicePrintBrowserTest,
                        StartPrintingDocumentDoneAccessDenied) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3302,7 +3306,8 @@
 // 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_P(PrintBackendPrintBrowserTestService, StartBasicPrint) {
+IN_PROC_BROWSER_TEST_P(SystemAccessProcessServicePrintBrowserTest,
+                       StartBasicPrint) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
 
@@ -3337,7 +3342,7 @@
   EXPECT_TRUE(stop_invoked());
 }
 
-IN_PROC_BROWSER_TEST_F(PrintBackendPrintBrowserTestInBrowser,
+IN_PROC_BROWSER_TEST_F(SystemAccessProcessInBrowserPrintBrowserTest,
                        StartBasicPrintCancel) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3371,7 +3376,7 @@
   EXPECT_FALSE(print_backend_service_use_detected());
 }
 
-IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_P(SystemAccessProcessServicePrintBrowserTest,
                        StartBasicPrintCancel) {
   AddPrinter("printer1");
   SetPrinterNameForSubsequentContexts("printer1");
@@ -3402,7 +3407,7 @@
   EXPECT_TRUE(stop_invoked());
 }
 
-IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_P(SystemAccessProcessServicePrintBrowserTest,
                        StartBasicPrintConcurrent) {
   ASSERT_TRUE(embedded_test_server()->Started());
   GURL url(embedded_test_server()->GetURL("/printing/test3.html"));
@@ -3435,7 +3440,7 @@
 #endif  // BUILDFLAG(IS_WIN)
 
 // https://crbug.com/1320681 flaky.
-IN_PROC_BROWSER_TEST_P(PrintBackendPrintBrowserTestService,
+IN_PROC_BROWSER_TEST_P(SystemAccessProcessServicePrintBrowserTest,
                        DISABLED_StartBasicPrintUseDefaultFails) {
   PrimeForFailInUseDefaultSettings();
 
diff --git a/chrome/browser/resources/certificate_viewer/certificate_viewer.html b/chrome/browser/resources/certificate_viewer/certificate_viewer.html
index f873d6ec..039425c5 100644
--- a/chrome/browser/resources/certificate_viewer/certificate_viewer.html
+++ b/chrome/browser/resources/certificate_viewer/certificate_viewer.html
@@ -18,7 +18,13 @@
       </div>
       <!-- General -->
       <div slot="panel" id="general" aria-labelledby="general-tab">
-        <div class="groups">
+        <div id="general-error" class="groups" hidden>
+          <div>
+            <h3 role="heading">$i18n{certError}</h3>
+          </div>
+        </div>
+
+        <div id="general-fields" class="groups">
           <!-- Issued to -->
           <div>
             <h3 role="heading">$i18n{issuedTo}</h3>
@@ -65,7 +71,9 @@
             <div class="attribute">$i18n{expiresOn}</div>
             <div id="expiry-date" class="value"></div>
           </div>
+        </div>
 
+        <div class="groups">
           <!-- Fingerprints -->
           <div>
             <h3 role="heading">$i18n{fingerprints}</h3>
diff --git a/chrome/browser/resources/certificate_viewer/certificate_viewer.ts b/chrome/browser/resources/certificate_viewer/certificate_viewer.ts
index b164bb1..a495c86d 100644
--- a/chrome/browser/resources/certificate_viewer/certificate_viewer.ts
+++ b/chrome/browser/resources/certificate_viewer/certificate_viewer.ts
@@ -20,6 +20,7 @@
 type CertificateInfo = {
   general: {[key: string]: string},
   hierarchy: TreeInfo[],
+  isError: boolean,
 };
 
 type TreeItemDetail = {
@@ -140,6 +141,12 @@
  * @param certInfo Certificate information in named fields.
  */
 function getCertificateInfo(certInfo: CertificateInfo) {
+  const generalError = document.querySelector<HTMLElement>('#general-error');
+  assert(generalError);
+  generalError.hidden = !certInfo.isError;
+  const generalFields = document.querySelector<HTMLElement>('#general-fields');
+  assert(generalFields);
+  generalFields.hidden = certInfo.isError;
   for (const key in certInfo.general) {
     const el = document.querySelector<HTMLElement>(`#${key}`);
     assert(el);
diff --git a/chrome/browser/resources/chromeos/accessibility/.eslintrc.js b/chrome/browser/resources/chromeos/accessibility/.eslintrc.js
index a657fe4c..de6bac6 100644
--- a/chrome/browser/resources/chromeos/accessibility/.eslintrc.js
+++ b/chrome/browser/resources/chromeos/accessibility/.eslintrc.js
@@ -4,7 +4,6 @@
 
 module.exports = {
   'rules' : {
-    'arrow-parens' : ['error', 'as-needed'],
     'arrow-spacing' : ['error'],
     'brace-style' : ['error', '1tbs'],
     'curly' : ['error', 'multi-line', 'consistent'],
diff --git a/chrome/browser/resources/chromeos/contact_center_insights/background.js b/chrome/browser/resources/chromeos/contact_center_insights/background.js
index 77bed44..121ff3b 100644
--- a/chrome/browser/resources/chromeos/contact_center_insights/background.js
+++ b/chrome/browser/resources/chromeos/contact_center_insights/background.js
@@ -87,10 +87,15 @@
   const metricData = new proto.reporting.MetricData();
   metricData.setTelemetryData(telemetryData);
 
+  // Also set metric timestamp (in ms) because the server also checks for these
+  // in addition to the ones set with the record (in microseconds) today.
+  const timestampMs = Date.now();
+  metricData.setTimestampMs(timestampMs);
+
   const record = new proto.reporting.Record();
   record.setDestination(proto.reporting.Destination.TELEMETRY_METRIC);
   record.setData(metricData.serializeBinary());
-  record.setTimestampUs(Date.now() * 1000);
+  record.setTimestampUs(timestampMs * 1000);
 
   // Prepare enqueue record request
   const request = {
diff --git a/chrome/browser/resources/chromeos/crostini_installer/DIR_METADATA b/chrome/browser/resources/chromeos/crostini_installer/DIR_METADATA
index b3cd940..06e627f 100644
--- a/chrome/browser/resources/chromeos/crostini_installer/DIR_METADATA
+++ b/chrome/browser/resources/chromeos/crostini_installer/DIR_METADATA
@@ -1,3 +1 @@
-monorail {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/resources/chromeos/crostini_upgrader/DIR_METADATA b/chrome/browser/resources/chromeos/crostini_upgrader/DIR_METADATA
index b3cd940..06e627f 100644
--- a/chrome/browser/resources/chromeos/crostini_upgrader/DIR_METADATA
+++ b/chrome/browser/resources/chromeos/crostini_upgrader/DIR_METADATA
@@ -1,3 +1 @@
-monorail {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/resources/new_tab_page/modules/cart/discount_consent_card.ts b/chrome/browser/resources/new_tab_page/modules/cart/discount_consent_card.ts
index 0007a0e..c33fe04a 100644
--- a/chrome/browser/resources/new_tab_page/modules/cart/discount_consent_card.ts
+++ b/chrome/browser/resources/new_tab_page/modules/cart/discount_consent_card.ts
@@ -215,9 +215,9 @@
   private getFaviconUrl_(url: string): string {
     const faviconUrl = new URL('chrome://favicon2/');
     faviconUrl.searchParams.set('size', '20');
-    faviconUrl.searchParams.set('scale_factor', '1x');
-    faviconUrl.searchParams.set('show_fallback_monogram', '');
-    faviconUrl.searchParams.set('page_url', url);
+    faviconUrl.searchParams.set('scaleFactor', '1x');
+    faviconUrl.searchParams.set('showFallbackMonogram', '');
+    faviconUrl.searchParams.set('pageUrl', url);
     return faviconUrl.href;
   }
 
diff --git a/chrome/browser/resources/new_tab_page/modules/cart/module.ts b/chrome/browser/resources/new_tab_page/modules/cart/module.ts
index 716cba6..93694944 100644
--- a/chrome/browser/resources/new_tab_page/modules/cart/module.ts
+++ b/chrome/browser/resources/new_tab_page/modules/cart/module.ts
@@ -182,9 +182,9 @@
   private getFaviconUrl_(url: string): string {
     const faviconUrl = new URL('chrome://favicon2/');
     faviconUrl.searchParams.set('size', '24');
-    faviconUrl.searchParams.set('scale_factor', '1x');
-    faviconUrl.searchParams.set('show_fallback_monogram', '');
-    faviconUrl.searchParams.set('page_url', url);
+    faviconUrl.searchParams.set('scaleFactor', '1x');
+    faviconUrl.searchParams.set('showFallbackMonogram', '');
+    faviconUrl.searchParams.set('pageUrl', url);
     return faviconUrl.href;
   }
 
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/DIR_METADATA b/chrome/browser/resources/settings/chromeos/crostini_page/DIR_METADATA
index 18d5982..06e627f 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/DIR_METADATA
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/DIR_METADATA
@@ -1,5 +1 @@
-buganizer {
-    # ChromeOS > Software > Guest OS > Crostini
-    component_id: 1122570
-}
-team_email: "clumptini@google.com"
\ No newline at end of file
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.js
index 62a72acb..88112f3 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/about_page_browser_proxy.js
@@ -177,6 +177,12 @@
   openFirmwareUpdatesPage() {}
 
   /**
+   * Requests the number of firmware updates.
+   * @return {!Promise<number>}
+   */
+  getFirmwareUpdateCount() {}
+
+  /**
    * Checks for available update and applies if it exists.
    */
   requestUpdate() {}
@@ -302,6 +308,11 @@
   }
 
   /** @override */
+  getFirmwareUpdateCount() {
+    return sendWithPromise('getFirmwareUpdateCount');
+  }
+
+  /** @override */
   requestUpdate() {
     chrome.send('requestUpdate');
   }
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
index b4fe552..f377bfc 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
@@ -39,6 +39,10 @@
     fill: var(--cros-icon-color-alert);
   }
 
+  #firmwareUpdateBadge {
+    --iron-icon-fill-color: var(--cros-icon-color-secondary);
+  }
+
   .settings-box .start {
     overflow-x: auto;
   }
@@ -56,6 +60,11 @@
       filter: invert(1);
     }
   }
+
+  .separator-firmware-updates-badge {
+    margin-inline-end: -4px;
+    margin-inline-start: 12px;
+  }
 </style>
 <iron-media-query query="(prefers-color-scheme: dark)"
     query-matches="{{isDarkModeActive_}}">
@@ -168,8 +177,18 @@
       <cr-link-row class="hr" id="firmwareUpdates"
           on-click="onFirmwareUpdatesClick_"
           hidden$="[[!showFirmwareUpdatesApp_]]"
-          label="$i18n{aboutFirmwareUpdates}" external
+          label="$i18n{aboutFirmwareUpdates}" external using-slotted-label
           deep-link-focus-id$="[[Setting.kFirmwareUpdates]]">
+        <iron-icon id="firmwareUpdateBadge"
+            icon$="[[getFirmwareUpdatesIcon_(firmwareUpdateCount_)]]"
+            hidden$="[[!shouldShowFirmwareUpdatesBadge_(
+              firmwareUpdateCount_)]]">
+        </iron-icon>
+        <div id="firmwareUpdateBadgeSeparator"
+            class="separator separator-firmware-updates-badge"
+            hidden$="[[!shouldShowFirmwareUpdatesBadge_(
+              firmwareUpdateCount_)]]">
+        </div>
       </cr-link-row>
       <cr-link-row class="hr" id="detailed-build-info-trigger"
           on-click="onDetailedBuildInfoClick_"
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js
index 4e195cf7..29ed018 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js
@@ -158,6 +158,12 @@
       },
 
       /** @private */
+      firmwareUpdateCount_: {
+        type: Number,
+        value: 0,
+      },
+
+      /** @private */
       showCrostini: Boolean,
 
       /** @private */
@@ -302,6 +308,12 @@
       this.hasInternetConnection_ = result;
     });
 
+    if (this.showFirmwareUpdatesApp_) {
+      this.aboutBrowserProxy_.getFirmwareUpdateCount().then(result => {
+        this.firmwareUpdateCount_ = result;
+      });
+    }
+
     if (Router.getInstance().getQueryParameters().get('checkForUpdate') ===
         'true') {
       this.onCheckUpdatesClick_();
@@ -467,6 +479,13 @@
     return this.currentUpdateStatusEvent_.status === UpdateStatus.FAILED;
   }
 
+  /**
+   * @return {boolean}
+   * @private
+   */
+  shouldShowFirmwareUpdatesBadge_() {
+    return this.showFirmwareUpdatesApp_ && this.firmwareUpdateCount_ > 0;
+  }
 
   /**
    * @return {string}
@@ -570,6 +589,22 @@
   }
 
   /**
+   * @return {string}
+   * @private
+   */
+  getFirmwareUpdatesIcon_() {
+    if (this.firmwareUpdateCount_ === 0) {
+      return '';
+    }
+
+    const maxBadgeId = 9;
+    // If the number of firmware updates is > 9, then we want to show
+    // the 9 badge.
+    const updateBadgeId = Math.min(this.firmwareUpdateCount_, maxBadgeId);
+    return `os-settings:counter-${updateBadgeId}`;
+  }
+
+  /**
    * @return {?string}
    * @private
    */
diff --git a/chrome/browser/resources/settings/chromeos/os_icons.html b/chrome/browser/resources/settings/chromeos/os_icons.html
index 617c9ba..7126bbcd 100644
--- a/chrome/browser/resources/settings/chromeos/os_icons.html
+++ b/chrome/browser/resources/settings/chromeos/os_icons.html
@@ -12,6 +12,40 @@
       <!-- Apps icon for Settings drawer -->
       <g id="apps"><rect width="20" height="20" fill="none"></rect><path d="M15 7C16.1 7 17 6.1 17 5C17 3.9 16.1 3 15 3C13.9 3 13 3.9 13 5C13 6.1 13.9 7 15 7Z"></path><path d="M5 17C6.1 17 7 16.1 7 15C7 13.9 6.1 13 5 13C3.9 13 3 13.9 3 15C3 16.1 3.9 17 5 17Z"></path><path d="M15 17C16.1 17 17 16.1 17 15C17 13.9 16.1 13 15 13C13.9 13 13 13.9 13 15C13 16.1 13.9 17 15 17Z"></path><path d="M12 15C12 16.1 11.1 17 10 17C8.9 17 8 16.1 8 15C8 13.9 8.9 13 10 13C11.1 13 12 13.9 12 15Z"></path><path d="M7 5C7 6.1 6.1 7 5 7C3.9 7 3 6.1 3 5C3 3.9 3.9 3 5 3C6.1 3 7 3.9 7 5Z"></path><path d="M10 7C11.1 7 12 6.1 12 5C12 3.9 11.1 3 10 3C8.9 3 8 3.9 8 5C8 6.1 8.9 7 10 7Z"></path><path d="M17 10C17 11.1 16.1 12 15 12C13.9 12 13 11.1 13 10C13 8.9 13.9 8 15 8C16.1 8 17 8.9 17 10Z"></path><path d="M5 12C6.1 12 7 11.1 7 10C7 8.9 6.1 8 5 8C3.9 8 3 8.9 3 10C3 11.1 3.9 12 5 12Z"></path><path d="M12 10C12 11.1 11.1 12 10 12C8.9 12 8 11.1 8 10C8 8.9 8.9 8 10 8C11.1 8 12 8.9 12 10Z"></path></g>
 
+      <!-- About page section -->
+      <g id="counter-1">
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M2 10C2 5.584 5.584 2 10 2C14.416 2 18 5.584 18 10C18 14.416 14.416 18 10 18C5.584 18 2 14.416 2 10ZM9.59448 14H11.1467V6.16895H10.9802L7.74146 7.3291V8.59131L9.59448 8.0166V14Z"></path>
+      </g>
+      <g id="counter-2">
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M2 10C2 5.584 5.584 2 10 2C14.416 2 18 5.584 18 10C18 14.416 14.416 18 10 18C5.584 18 2 14.416 2 10ZM7.37622 14H12.7366V12.7485H9.37427L11.1521 10.874C11.6391 10.3405 11.9828 9.87321 12.1833 9.47217C12.3839 9.07112 12.4841 8.67725 12.4841 8.29053C12.4841 7.58512 12.2612 7.03906 11.8154 6.65234C11.3696 6.26562 10.7439 6.07227 9.93823 6.07227C9.41186 6.07227 8.941 6.18416 8.52563 6.40796C8.11027 6.63176 7.7889 6.94059 7.56152 7.33447C7.33415 7.72835 7.22046 8.16341 7.22046 8.63965H8.77808C8.77808 8.24577 8.87923 7.92798 9.08154 7.68628C9.28385 7.44458 9.56046 7.32373 9.91138 7.32373C10.2372 7.32373 10.4879 7.42309 10.6633 7.62183C10.8388 7.82056 10.9265 8.09359 10.9265 8.44092C10.9265 8.69515 10.8433 8.9637 10.6768 9.24658C10.5103 9.52946 10.2533 9.86068 9.90601 10.2402L7.37622 12.9365V14Z"></path>
+      </g>
+      <g id="counter-3">
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M2 10C2 5.584 5.584 2 10 2C14.416 2 18 5.584 18 10C18 14.416 14.416 18 10 18C5.584 18 2 14.416 2 10ZM9.78247 9.40234H8.95532V10.6162H9.7771C10.6365 10.6162 11.0662 11.0065 11.0662 11.7871C11.0662 12.1094 10.9614 12.3681 10.752 12.5632C10.5425 12.7584 10.2533 12.856 9.88452 12.856C9.56225 12.856 9.29102 12.7629 9.0708 12.5767C8.85058 12.3905 8.74048 12.1506 8.74048 11.8569H7.18823C7.18823 12.5337 7.4362 13.078 7.93213 13.4897C8.42806 13.9015 9.06632 14.1074 9.84692 14.1074C10.6812 14.1074 11.3517 13.898 11.8584 13.479C12.3651 13.0601 12.6184 12.5033 12.6184 11.8086C12.6184 11.3789 12.5101 11.0065 12.2935 10.6914C12.0768 10.3763 11.7483 10.14 11.3079 9.98242C11.6624 9.82129 11.9488 9.59033 12.1672 9.28955C12.3857 8.98877 12.4949 8.65934 12.4949 8.30127C12.4949 7.6066 12.2603 7.06144 11.7913 6.66577C11.3222 6.2701 10.6741 6.07227 9.84692 6.07227C9.37068 6.07227 8.93474 6.16357 8.53906 6.34619C8.14339 6.52881 7.83545 6.78214 7.61523 7.1062C7.39502 7.43026 7.28491 7.79638 7.28491 8.20459H8.83716C8.83716 7.9432 8.93742 7.73104 9.13794 7.56812C9.33846 7.40519 9.58732 7.32373 9.88452 7.32373C10.214 7.32373 10.4727 7.41146 10.6606 7.58691C10.8486 7.76237 10.9426 8.00765 10.9426 8.32275C10.9426 8.6486 10.8477 8.90999 10.658 9.10693C10.4682 9.30387 10.1764 9.40234 9.78247 9.40234Z"></path>
+      </g>
+      <g id="counter-4">
+        <path d="M10.4163 11.0566H8.68677L10.3142 8.47314L10.4163 8.2959V11.0566Z"></path>
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M10 2C5.584 2 2 5.584 2 10C2 14.416 5.584 18 10 18C14.416 18 18 14.416 18 10C18 5.584 14.416 2 10 2ZM11.9685 11.0566H12.8547V12.3081H11.9685V14H10.4163V12.3081H7.20972L7.13989 11.3306L10.4001 6.17969H11.9685V11.0566Z"></path>
+      </g>
+      <g id="counter-5">
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M2 10C2 5.584 5.584 2 10 2C14.416 2 18 5.584 18 10C18 14.416 14.416 18 10 18C5.584 18 2 14.416 2 10ZM8.05835 6.17969L7.60718 10.1543L8.84253 10.4604L8.99292 10.3208C9.22209 10.1274 9.52108 10.0308 9.88989 10.0308C10.2909 10.0308 10.6007 10.1489 10.8191 10.3853C11.0375 10.6216 11.1467 10.9617 11.1467 11.4058C11.1467 11.8677 11.0518 12.2249 10.8621 12.4773C10.6723 12.7297 10.4019 12.856 10.051 12.856C9.73592 12.856 9.4808 12.7655 9.28564 12.5847C9.09049 12.4039 8.97681 12.1506 8.94458 11.8247H7.40845C7.42277 12.2687 7.5472 12.6644 7.78174 13.0117C8.01628 13.3591 8.33585 13.6285 8.74048 13.8201C9.1451 14.0116 9.58374 14.1074 10.0564 14.1074C10.5971 14.1074 11.0662 13.9973 11.4636 13.7771C11.8611 13.5569 12.1663 13.2472 12.3794 12.8479C12.5924 12.4486 12.699 11.9966 12.699 11.4917C12.699 10.661 12.4877 10.0147 12.0652 9.55273C11.6427 9.09082 11.059 8.85986 10.3142 8.85986C9.89884 8.85986 9.50676 8.95833 9.13794 9.15527L9.3313 7.47412H12.4412V6.17969H8.05835Z"></path>
+      </g>
+      <g id="counter-6">
+        <path d="M9.39038 10.2107C9.59448 10.08 9.82186 10.0146 10.0725 10.0146C10.4234 10.0146 10.7027 10.1453 10.9104 10.4067C11.1181 10.6681 11.2219 11.0119 11.2219 11.438C11.2219 11.8569 11.119 12.198 10.9131 12.4612C10.7072 12.7244 10.4377 12.856 10.1047 12.856C9.73592 12.856 9.44946 12.71 9.24536 12.4182C9.04126 12.1264 8.93921 11.7209 8.93921 11.2017V10.729C9.03589 10.5142 9.18628 10.3414 9.39038 10.2107Z"></path>
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M10 2C5.584 2 2 5.584 2 10C2 14.416 5.584 18 10 18C14.416 18 18 14.416 18 10C18 5.584 14.416 2 10 2ZM11.5872 6.09912V7.37744H11.4368C10.7349 7.38818 10.1701 7.5708 9.74219 7.92529C9.31429 8.27979 9.05737 8.77213 8.97144 9.40234C9.3868 8.97982 9.91137 8.76855 10.5452 8.76855C11.2255 8.76855 11.7662 9.01204 12.1672 9.49902C12.5683 9.986 12.7688 10.6269 12.7688 11.4219C12.7688 11.9303 12.6587 12.3905 12.4385 12.8022C12.2183 13.214 11.9067 13.5345 11.5039 13.7637C11.1011 13.9928 10.6454 14.1074 10.137 14.1074C9.31339 14.1074 8.64828 13.821 8.1416 13.248C7.63493 12.6751 7.38159 11.9106 7.38159 10.9546V10.396C7.38159 9.54736 7.54183 8.7981 7.8623 8.14819C8.18278 7.49829 8.6429 6.9952 9.24268 6.63892C9.84245 6.28263 10.538 6.1027 11.3293 6.09912H11.5872Z"></path>
+      </g>
+      <g id="counter-7">
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M2 10C2 5.584 5.584 2 10 2C14.416 2 18 5.584 18 10C18 14.416 14.416 18 10 18C5.584 18 2 14.416 2 10ZM9.66968 14L12.6936 7.0498V6.17969H7.17212V7.43652H11.0608L8.03149 14H9.66968Z"></path>
+      </g>
+      <g id="counter-8">
+        <path d="M11.0823 11.7441C11.0823 11.404 10.9838 11.1318 10.7869 10.9277C10.5899 10.7236 10.325 10.6216 9.99194 10.6216C9.66251 10.6216 9.39933 10.7227 9.20239 10.925C9.00545 11.1274 8.90698 11.4004 8.90698 11.7441C8.90698 12.0772 9.00366 12.3457 9.19702 12.5498C9.39038 12.7539 9.65893 12.856 10.0027 12.856C10.3393 12.856 10.6034 12.7575 10.7949 12.5605C10.9865 12.3636 11.0823 12.0915 11.0823 11.7441Z"></path>
+        <path d="M10.6794 7.60034C10.8406 7.78475 10.9211 8.02913 10.9211 8.3335C10.9211 8.64502 10.8415 8.89567 10.6821 9.08545C10.5228 9.27523 10.2963 9.37012 10.0027 9.37012C9.70906 9.37012 9.48169 9.27523 9.32056 9.08545C9.15942 8.89567 9.07886 8.64502 9.07886 8.3335C9.07886 8.01839 9.15942 7.77132 9.32056 7.59229C9.48169 7.41325 9.70727 7.32373 9.99731 7.32373C10.2909 7.32373 10.5183 7.41593 10.6794 7.60034Z"></path>
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M2 10C2 5.584 5.584 2 10 2C14.416 2 18 5.584 18 10C18 14.416 14.416 18 10 18C5.584 18 2 14.416 2 10ZM12.1887 9.26807C12.3785 8.97445 12.4734 8.63786 12.4734 8.2583C12.4734 7.58512 12.2505 7.05249 11.8047 6.6604C11.3589 6.26831 10.7564 6.07227 9.99731 6.07227C9.23462 6.07227 8.63127 6.2701 8.18726 6.66577C7.74324 7.06144 7.52124 7.59228 7.52124 8.2583C7.52124 8.63786 7.61523 8.97445 7.80322 9.26807C7.99121 9.56169 8.25171 9.79622 8.58472 9.97168C8.20874 10.1507 7.90975 10.4014 7.68774 10.7236C7.46574 11.0459 7.35474 11.4237 7.35474 11.8569C7.35474 12.548 7.59285 13.0959 8.06909 13.5005C8.54533 13.9051 9.18986 14.1074 10.0027 14.1074C10.8155 14.1074 11.4583 13.906 11.9309 13.5032C12.4036 13.1003 12.6399 12.5516 12.6399 11.8569C12.6399 11.4237 12.5289 11.0468 12.3069 10.7263C12.0849 10.4058 11.7841 10.1543 11.4045 9.97168C11.7376 9.79622 11.9989 9.56169 12.1887 9.26807Z"></path>
+      </g>
+      <g id="counter-9">
+        <path d="M10.6177 10.0898C10.4368 10.2188 10.2211 10.2832 9.97046 10.2832C9.61596 10.2832 9.34115 10.1462 9.146 9.87231C8.95085 9.59839 8.85327 9.24837 8.85327 8.82227C8.85327 8.39258 8.95353 8.0354 9.15405 7.75073C9.35457 7.46606 9.61059 7.32373 9.92212 7.32373C10.2587 7.32373 10.5273 7.46875 10.7278 7.75879C10.9283 8.04883 11.0286 8.45703 11.0286 8.9834V9.62256C10.9355 9.80518 10.7985 9.96094 10.6177 10.0898Z"></path>
+        <path fill-rule="evenodd" clip-rule="evenodd" d="M10 2C5.584 2 2 5.584 2 10C2 14.416 5.584 18 10 18C14.416 18 18 14.416 18 10C18 5.584 14.416 2 10 2ZM11.0071 10.874C10.6025 11.2715 10.1298 11.4702 9.58911 11.4702C8.89803 11.4702 8.34481 11.233 7.92944 10.7585C7.51408 10.2841 7.3064 9.64405 7.3064 8.83838C7.3064 8.32633 7.41829 7.85637 7.64209 7.42847C7.86589 7.00057 8.1783 6.66756 8.57935 6.42944C8.98039 6.19132 9.43156 6.07227 9.93286 6.07227C10.4485 6.07227 10.9068 6.20117 11.3079 6.45898C11.7089 6.7168 12.0204 7.0874 12.2424 7.5708C12.4644 8.0542 12.5772 8.60742 12.5808 9.23047V9.80518C12.5808 11.1086 12.2568 12.1326 11.6086 12.8774C10.9605 13.6222 10.0421 14.0197 8.85327 14.0698L8.47192 14.0752V12.7808L8.81567 12.7754C10.1656 12.7145 10.8961 12.0807 11.0071 10.874Z"></path>
+      </g>
+
       <!-- Crostini Mascot icon for Settings drawer -->
       <g id="crostini-mascot" fill-rule="evenodd" viewBox="0 0 24 24">
         <rect width="24" height="24" fill="none"></rect>
diff --git a/chrome/browser/resources/usb_internals/BUILD.gn b/chrome/browser/resources/usb_internals/BUILD.gn
index c68fad9..f954150 100644
--- a/chrome/browser/resources/usb_internals/BUILD.gn
+++ b/chrome/browser/resources/usb_internals/BUILD.gn
@@ -36,7 +36,7 @@
 
 web_components_files = [ "app.js" ]
 non_web_components_files = [
-  "descriptor_panel.js",
+  "descriptor_panel.ts",
   "devices_page.js",
 ]
 
@@ -45,17 +45,26 @@
 }
 
 copy("copy_files") {
-  deps = [ "//chrome/browser/ui/webui/usb_internals:mojo_bindings_webui_js" ]
-  sources = non_web_components_files + [ "${root_gen_dir}/mojom-webui/chrome/browser/ui/webui/usb_internals/usb_internals.mojom-webui.js" ]
+  deps = [
+    "//chrome/browser/ui/webui/usb_internals:mojo_bindings_webui_js",
+    "//services/device/public/mojom:usb_webui_js",
+  ]
+  sources = non_web_components_files + [
+              "$root_gen_dir/mojom-webui/services/device/public/mojom/usb_device.mojom-webui.js",
+              "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/usb_internals/usb_internals.mojom-webui.js",
+            ]
   outputs = [ "$target_gen_dir/{{source_file_part}}" ]
 }
 
 ts_library("build_ts") {
   root_dir = target_gen_dir
-  in_files = web_components_files + non_web_components_files +
-             [ "usb_internals.mojom-webui.js" ]
+  in_files = web_components_files + non_web_components_files + [
+               "usb_internals.mojom-webui.js",
+               "usb_device.mojom-webui.js",
+             ]
   out_dir = "$target_gen_dir/tsc"
   tsconfig_base = "tsconfig_base.json"
+
   deps = [
     "//ui/webui/resources:library",
     "//ui/webui/resources/mojo:library",
diff --git a/chrome/browser/resources/usb_internals/descriptor_panel.js b/chrome/browser/resources/usb_internals/descriptor_panel.ts
similarity index 72%
rename from chrome/browser/resources/usb_internals/descriptor_panel.js
rename to chrome/browser/resources/usb_internals/descriptor_panel.ts
index 18eb71eee..85c016e 100644
--- a/chrome/browser/resources/usb_internals/descriptor_panel.js
+++ b/chrome/browser/resources/usb_internals/descriptor_panel.ts
@@ -10,8 +10,9 @@
 import 'chrome://resources/cr_elements/cr_tree/cr_tree.js';
 import 'chrome://resources/cr_elements/cr_tree/cr_tree_item.js';
 
-import {assert, assertInstanceof} from 'chrome://resources/js/assert.m.js';
-import {queryRequiredElement} from 'chrome://resources/js/util.m.js';
+import {CrTreeElement} from 'chrome://resources/cr_elements/cr_tree/cr_tree.js';
+import {CrTreeItemElement} from 'chrome://resources/cr_elements/cr_tree/cr_tree_item.js';
+import {assert} from 'chrome://resources/js/assert_ts.js';
 
 import {UsbControlTransferParams, UsbControlTransferRecipient, UsbControlTransferType, UsbDeviceInterface, UsbTransferStatus} from './usb_device.mojom-webui.js';
 
@@ -40,7 +41,6 @@
 const INTERFACE_DESCRIPTOR_LENGTH = 9;
 const ENDPOINT_DESCRIPTOR_LENGTH = 7;
 const BOS_DESCRIPTOR_HEADER_LENGTH = 5;
-const PLATFORM_DESCRIPTOR_HEADER_LENGTH = 20;
 const MAX_URL_DESCRIPTOR_LENGTH = 0xFF;
 
 const CONTROL_TRANSFER_TIMEOUT_MS = 2000;  // 2 seconds
@@ -64,7 +64,6 @@
 
 // These constants are defined by the WebUSB specification:
 // http://wicg.github.io/webusb/
-const WEB_USB_DESCRIPTOR_LENGTH = 24;
 
 const GET_URL_REQUEST = 0x02;
 
@@ -79,7 +78,6 @@
 
 // These constants are defined by Microsoft OS 2.0 Descriptors Specification
 // (July, 2018).
-const MS_OS_20_DESCRIPTOR_SET_INFORMATION_LENGTH = 8;
 
 const MS_OS_20_DESCRIPTOR_INDEX = 0x07;
 const MS_OS_20_SET_ALT_ENUMERATION = 0x08;
@@ -116,51 +114,25 @@
   0x64, 0x8A, 0x9F
 ];
 
-// TODO (rbpotter): Remove these temporary definitions after migrating to TS.
-/**
- * @typedef {{
- *   expanded: boolean,
- *   add: function(CrTreeItemElement): void,
- *   labelElement: HTMLElement,
- *   rowElement: HTMLElement,
- *   forceHoverStyle: function(boolean): void,
- * }}
- */
-export let CrTreeItemElement;
-
-/**
- * @typedef {{
- *   add: function(CrTreeItemElement): void,
- *   detail: {payload: Object, children: Object},
- *   removeTreeItem: function(CrTreeItemElement): void,
- *   expanded: boolean,
- *   items: Array<CrTreeItemElement>,
- *   selectedItem: CrTreeItemElement,
- * }}
- */
-export let CrTreeElement;
-
-
 export class DescriptorPanel {
-  /**
-   * @param {!UsbDeviceInterface} usbDeviceProxy
-   * @param {!HTMLElement} rootElement
-   */
-  constructor(usbDeviceProxy, rootElement) {
-    /** @type {!UsbDeviceInterface} */
-    this.usbDeviceProxy_ = usbDeviceProxy;
+  private usbDeviceProxy_: UsbDeviceInterface;
+  private rootElement_: HTMLElement;
+  private stringDescriptorPanel_: DescriptorPanel|null = null;
+  private languageCodesListElement_: HTMLElement|null = null;
+  private indexInput_: HTMLInputElement|null = null;
+  stringDescriptorIndexes: Set<number> = new Set();
+  indexesListElement: HTMLElement|null = null;
 
-    /** @type {!HTMLElement} */
+  constructor(usbDeviceProxy: UsbDeviceInterface, rootElement: HTMLElement) {
+    this.usbDeviceProxy_ = usbDeviceProxy;
     this.rootElement_ = rootElement;
   }
 
   /**
    * Adds the reference of the string descriptor panel of the device for
    * string descriptor functionality.
-   * @param {!DescriptorPanel} stringDescriptorPanel
    */
-  setStringDescriptorPanel(stringDescriptorPanel) {
-    /** @type {!DescriptorPanel} */
+  setStringDescriptorPanel(stringDescriptorPanel: DescriptorPanel) {
     this.stringDescriptorPanel_ = stringDescriptorPanel;
   }
 
@@ -175,40 +147,51 @@
         .forEach(el => el.remove());
   }
 
+  private getButtonElementFromTemplate_(): HTMLButtonElement {
+    const buttonTemplate =
+        (this.rootElement_.getRootNode() as DocumentFragment | HTMLElement)
+            .querySelector<HTMLTemplateElement>('#raw-data-tree-button');
+    assert(buttonTemplate);
+    const button = document.importNode(buttonTemplate.content, true)
+                       .querySelector('button');
+    assert(button);
+    return button;
+  }
+
   /**
    * Adds a button for getting string descriptor to the string descriptor
    * index item, and adds an autocomplete value to the index input area in
    * the string descriptor panel.
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The offset of the string descriptor index field.
-   * @param {!CrTreeItemElement} item
-   * @param {string} fieldLabel
-   * @private
+   * @param offset The offset of the string descriptor index field.
    */
-  renderIndexItem_(rawData, offset, item, fieldLabel) {
-    const index = rawData[offset];
+  private renderIndexItem_(
+      rawData: Uint8Array, offset: number, item: CrTreeItemElement,
+      fieldLabel: string) {
+    const index = rawData[offset]!;
     if (index > 0) {
+      assert(this.stringDescriptorPanel_);
       if (!this.stringDescriptorPanel_.stringDescriptorIndexes.has(index)) {
         const optionElement = document.createElement('option');
-        optionElement.label = index;
-        optionElement.value = index;
+        optionElement.label = index.toString();
+        optionElement.value = index.toString();
+        assert(this.stringDescriptorPanel_.indexesListElement);
         this.stringDescriptorPanel_.indexesListElement.appendChild(
             optionElement);
 
         this.stringDescriptorPanel_.stringDescriptorIndexes.add(index);
       }
 
-      const buttonTemplate = queryRequiredElement(
-          '#raw-data-tree-button',
-          /** @type {!DocumentFragment} */ (this.rootElement_.getRootNode()));
-      const button = document.importNode(buttonTemplate.content, true)
-                         .querySelector('button');
+      const button = this.getButtonElementFromTemplate_();
       item.labelElement.appendChild(button);
       button.style.marginInlineStart = '16px';
-      button.addEventListener('click', (event) => {
+      button.addEventListener('click', (event: MouseEvent) => {
         event.stopPropagation();
         // Clear the previous string descriptors.
-        item.shadowRoot.querySelector('.tree-children').textContent = '';
+        const children =
+            item.shadowRoot!.querySelector<HTMLElement>('.tree-children');
+        assert(children);
+        children.textContent = '';
+        assert(this.stringDescriptorPanel_);
         this.stringDescriptorPanel_.clearView();
         this.stringDescriptorPanel_.getStringDescriptorForAllLanguages_(
             index, item);
@@ -225,26 +208,22 @@
 
   /**
    * Adds a button for getting URL descriptor.
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The offset of the URL descriptor index.
-   * @param {!CrTreeItemElement} item
-   * @param {string} fieldLabel Not used in this function, but used to match
-   *     other extraTreeItemFormatter.
-   * @private
+   * @param offset The offset of the URL descriptor index.
    */
-  renderUrlDescriptorIndexItem_(rawData, offset, item, fieldLabel) {
-    const index = rawData[offset];
+  private renderUrlDescriptorIndexItem_(
+      rawData: Uint8Array, offset: number, item: CrTreeItemElement,
+      _fieldLabel: string) {
+    const index = rawData[offset]!;
     if (index > 0) {
-      const buttonTemplate = queryRequiredElement(
-          '#raw-data-tree-button',
-          /** @type {!DocumentFragment} */ (this.rootElement_.getRootNode()));
-      const button = document.importNode(buttonTemplate.content, true)
-                         .querySelector('button');
+      const button = this.getButtonElementFromTemplate_();
       item.labelElement.appendChild(button);
-      button.addEventListener('click', (event) => {
+      button.addEventListener('click', (event: MouseEvent) => {
         event.stopPropagation();
         // Clear the previous URL descriptors.
-        item.shadowRoot.querySelector('.tree-children').textContent = '';
+        const children =
+            item.shadowRoot!.querySelector<HTMLElement>('.tree-children');
+        assert(children);
+        children.textContent = '';
         this.getUrlDescriptor_(
             rawData, offset - WEB_USB_URL_DESCRIPTOR_INDEX_OFFSET, item);
       });
@@ -255,33 +234,24 @@
    * Adds a button for getting the Microsoft OS 2.0 vendor-specific descriptor
    * to the Microsoft OS 2.0 descriptor set information vendor-specific code
    * item.
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the Microsoft OS 2.0
+   * @param offset The start offset of the Microsoft OS 2.0
    *     descriptor set information.
-   * @param {!CrTreeItemElement} item
-   * @param {string} fieldLabel Not used in this function, but used to match
-   *     other extraTreeItemFormatter.
-   * @private
    */
-  async renderMsOs20DescriptorVendorSpecific_(
-      rawData, offset, item, fieldLabel) {
+  private async renderMsOs20DescriptorVendorSpecific_(
+      rawData: Uint8Array, offset: number, item: CrTreeItemElement) {
     // Use the vendor specified code and the length of Microsoft OS 2.0
     // descriptor Set that contained in Microsoft OS 2.0 descriptor Set Info
     // to get Microsoft OS 2.0 Descriptor Set.
     // This is defined by Microsoft OS 2.0 Descriptors Specification (July,
     // 2018).
-    const vendorCode = rawData[offset + MS_OS_20_VENDOR_CODE_ITEM_OFFSET];
+    const vendorCode = rawData[offset + MS_OS_20_VENDOR_CODE_ITEM_OFFSET]!;
     const data = new DataView(rawData.buffer, offset);
     const msOs20DescriptorSetLength =
         data.getUint16(MS_OS_20_SET_TOTAL_LENGTH_OFFSET, true);
 
-    const buttonTemplate = queryRequiredElement(
-        '#raw-data-tree-button',
-        /** @type {!DocumentFragment} */ (this.rootElement_.getRootNode()));
-    const button = document.importNode(buttonTemplate.content, true)
-                       .querySelector('button');
+    const button = this.getButtonElementFromTemplate_();
     item.labelElement.appendChild(button);
-    button.addEventListener('click', async (event) => {
+    button.addEventListener('click', async (event: MouseEvent) => {
       event.stopPropagation();
       // Clear all the descriptor display elements except the first one, which
       // displays the original BOS descriptor.
@@ -299,30 +269,22 @@
   /**
    * Adds a button for sending a Microsoft OS 2.0 descriptor set alternate
    * enumeration command to the USB device.
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the Microsoft OS 2.0
+   * @param offset The start offset of the Microsoft OS 2.0
    *     descriptor set information.
-   * @param {!CrTreeItemElement} item
-   * @param {string} fieldLabel Not used in this function, but used to match
-   *     other extraTreeItemFormatter.
-   * @private
    */
-  async renderMsOs20DescriptorSetAltEnum_(rawData, offset, item, fieldLabel) {
+  private async renderMsOs20DescriptorSetAltEnum_(
+      rawData: Uint8Array, offset: number, item: CrTreeItemElement) {
     // Use the vendor specified code, alternate enumeration code to send a
     // Microsoft OS 2.0 set alternate enumeration command.
     // This is defined by Microsoft OS 2.0 Descriptors Specification (July,
     // 2018).
-    const altEnumCode = rawData[offset + MS_OS_20_ALT_ENUM_CODE_ITEM_OFFSET];
+    const altEnumCode = rawData[offset + MS_OS_20_ALT_ENUM_CODE_ITEM_OFFSET]!;
     if (altEnumCode !== 0) {
-      const vendorCode = rawData[offset + MS_OS_20_VENDOR_CODE_ITEM_OFFSET];
+      const vendorCode = rawData[offset + MS_OS_20_VENDOR_CODE_ITEM_OFFSET]!;
 
-      const buttonTemplate = queryRequiredElement(
-          '#raw-data-tree-button',
-          /** @type {!DocumentFragment} */ (this.rootElement_.getRootNode()));
-      const button = document.importNode(buttonTemplate.content, true)
-                         .querySelector('button');
+      const button = this.getButtonElementFromTemplate_();
       item.labelElement.appendChild(button);
-      button.addEventListener('click', async (event) => {
+      button.addEventListener('click', async (event: MouseEvent) => {
         event.stopPropagation();
         await this.sendMsOs20DescriptorSetAltEnumCommand_(
             vendorCode, altEnumCode);
@@ -333,19 +295,14 @@
   /**
    * Changes the display text in tree item for the Microsoft OS 2.0 registry
    * property descriptor.
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the registry Property
+   * @param offset The start offset of the registry Property
    *     descriptor.
-   * @param {!CrTreeItemElement} item
-   * @param {string} fieldLabel Not used in this function, but used to match
-   *     other extraTreeItemFormatter.
-   * @param {number} featureRegistryPropertyDataType
-   * @private
    */
-  renderFeatureRegistryPropertyDataItem_(
-      rawData, offset, item, fieldLabel, featureRegistryPropertyDataType,
-      length) {
-    let data;
+  private renderFeatureRegistryPropertyDataItem_(
+      rawData: Uint8Array, offset: number, item: CrTreeItemElement,
+      _fieldLabel: string, featureRegistryPropertyDataType: number,
+      length: number) {
+    let data: DataView;
     switch (featureRegistryPropertyDataType) {
       case MS_OS_20_FEATURE_REG_PROPERTY_DATA_TYPE_REG_BINARY:
         break;
@@ -375,17 +332,12 @@
   /**
    * Renders a view to display standard descriptor hex data in both tree view
    * and raw form view.
-   * @param {!Uint8Array} data
-   * @param {number=} languageCode
-   * @param {CrTreeItemElement=} treeItem
-   * @private
    */
-  async renderStandardDescriptor_(
-      data, languageCode = 0, treeItem = undefined) {
+  private async renderStandardDescriptor_(
+      data: Uint8Array, languageCode: number = 0,
+      treeItem?: CrTreeItemElement) {
     const displayElement = addNewDescriptorDisplayElement(this.rootElement_);
-    /** @type {!CrTreeElement} */
     const rawDataTreeRoot = displayElement.rawDataTreeRoot;
-    /** @type {!HTMLElement} */
     const rawDataByteElement = displayElement.rawDataByteElement;
 
     renderRawDataBytes(rawDataByteElement, data);
@@ -405,8 +357,8 @@
     // Stop if accessing the descriptor type would cause us to read past the
     // end of the buffer.
     while (offset + STANDARD_DESCRIPTOR_TYPE_OFFSET < data.length) {
-      const length = data[offset + STANDARD_DESCRIPTOR_LENGTH_OFFSET];
-      const descriptorType = data[offset + STANDARD_DESCRIPTOR_TYPE_OFFSET];
+      const length = data[offset + STANDARD_DESCRIPTOR_LENGTH_OFFSET]!;
+      const descriptorType = data[offset + STANDARD_DESCRIPTOR_TYPE_OFFSET]!;
       switch (descriptorType) {
         case DEVICE_DESCRIPTOR_TYPE:
           this.renderDeviceDescriptor_(
@@ -415,7 +367,7 @@
         case CONFIGURATION_DESCRIPTOR_TYPE:
           if (CONFIGURATION_DESCRIPTOR_NUM_INTERFACES_OFFSET < length) {
             expectNumInterfaces =
-                data[offset + CONFIGURATION_DESCRIPTOR_NUM_INTERFACES_OFFSET];
+                data[offset + CONFIGURATION_DESCRIPTOR_NUM_INTERFACES_OFFSET]!;
           }
           this.renderConfigurationDescriptor_(
               rawDataTreeRoot, rawDataByteElement, data, offset);
@@ -428,7 +380,7 @@
         case INTERFACE_DESCRIPTOR_TYPE:
           if (INTERFACE_DESCRIPTOR_NUM_ENDPOINTS_OFFSET < length) {
             expectNumEndpoints +=
-                data[offset + INTERFACE_DESCRIPTOR_NUM_ENDPOINTS_OFFSET];
+                data[offset + INTERFACE_DESCRIPTOR_NUM_ENDPOINTS_OFFSET]!;
           }
           lastInterfaceItem = this.renderInterfaceDescriptor_(
               rawDataTreeRoot, rawDataByteElement, data, offset,
@@ -445,7 +397,7 @@
           this.renderBosDescriptor_(
               rawDataTreeRoot, rawDataByteElement, data, offset);
           expectNumDevCapabilities =
-              data[BOS_DESCRIPTOR_NUM_DEVICE_CAPABILITIES_OFFSET];
+              data[BOS_DESCRIPTOR_NUM_DEVICE_CAPABILITIES_OFFSET]!;
           break;
         case DEVICE_CAPABILITY_DESCRIPTOR_TYPE:
           await this.renderDeviceCapabilityDescriptor_(
@@ -490,8 +442,7 @@
    * Gets device descriptor of current device, and display it.
    */
   async getDeviceDescriptor() {
-    /** @type {!UsbControlTransferParams} */
-    const usbControlTransferParams = {
+    const usbControlTransferParams: UsbControlTransferParams = {
       type: UsbControlTransferType.STANDARD,
       recipient: UsbControlTransferRecipient.DEVICE,
       request: GET_DESCRIPTOR_REQUEST,
@@ -509,7 +460,7 @@
           this.rootElement_);
       this.renderStandardDescriptor_(new Uint8Array(response.data.buffer));
     } catch (e) {
-      showError(e.message, this.rootElement_);
+      showError((e as Error).message, this.rootElement_);
     } finally {
       await this.usbDeviceProxy_.close();
     }
@@ -518,14 +469,11 @@
   /**
    * Renders a view to display device descriptor hex data in both tree view
    * and raw form.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the device descriptor.
-   * @private
+   * @param offset The start offset of the device descriptor.
    */
-  async renderDeviceDescriptor_(
-      rawDataTreeRoot, rawDataByteElement, rawData, offset) {
+  private async renderDeviceDescriptor_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, offset: number) {
     const fields = [
       {
         label: `Length (should be ${DEVICE_DESCRIPTOR_LENGTH}): `,
@@ -606,17 +554,16 @@
         rawDataTreeRoot, rawDataByteElement, fields, rawData, offset,
         this.rootElement_);
 
-    // window.deviceDescriptorCompleteFn() provides a hook for the test suite
-    // to perform test actions after the device descriptor is rendered.
-    window.deviceDescriptorCompleteFn();
+    document.body.dispatchEvent(new CustomEvent(
+        'device-descriptor-complete-for-test',
+        {bubbles: true, composed: true}));
   }
 
   /**
    * Gets configuration descriptor of current device, and display it.
    */
   async getConfigurationDescriptor() {
-    /** @type {!UsbControlTransferParams} */
-    const usbControlTransferParams = {
+    const usbControlTransferParams: UsbControlTransferParams = {
       type: UsbControlTransferType.STANDARD,
       recipient: UsbControlTransferRecipient.DEVICE,
       request: GET_DESCRIPTOR_REQUEST,
@@ -647,7 +594,7 @@
           this.rootElement_);
       this.renderStandardDescriptor_(new Uint8Array(response.data.buffer));
     } catch (e) {
-      showError(e.message, this.rootElement_);
+      showError((e as Error).message, this.rootElement_);
     } finally {
       await this.usbDeviceProxy_.close();
     }
@@ -656,14 +603,11 @@
   /**
    * Renders a view to display configuration descriptor hex data in both tree
    * view and raw form.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the configuration descriptor.
-   * @private
+   * @param offset The start offset of the configuration descriptor.
    */
-  async renderConfigurationDescriptor_(
-      rawDataTreeRoot, rawDataByteElement, rawData, offset) {
+  private async renderConfigurationDescriptor_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, offset: number) {
     const fields = [
       {
         label: `Length (should be ${CONFIGURATION_DESCRIPTOR_LENGTH}): `,
@@ -716,17 +660,12 @@
   /**
    * Renders a tree item to display interface descriptor at index
    * indexInterface.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the interface
-   *     descriptor.
-   * @param {number} indexInterface
-   * @return {!CrTreeItemElement}
-   * @private
+   * @param offset The start offset of the interface descriptor.
    */
-  renderInterfaceDescriptor_(
-      rawDataTreeRoot, rawDataByteElement, rawData, offset, indexInterface) {
+  private renderInterfaceDescriptor_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, offset: number,
+      indexInterface: number): CrTreeItemElement {
     const parentClassName = `descriptor-interface-${indexInterface}`;
     const interfaceItem =
         customTreeItem(`Interface ${indexInterface}`, parentClassName);
@@ -791,16 +730,13 @@
   /**
    * Renders a tree item to display endpoint descriptor at index
    * indexEndpoint.
-   * @param {!CrTreeElement|!CrTreeItemElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the endpoint
+   * @param offset The start offset of the endpoint
    *     descriptor.
-   * @param {number} indexEndpoint
-   * @private
    */
-  renderEndpointDescriptor_(
-      rawDataTreeRoot, rawDataByteElement, rawData, offset, indexEndpoint) {
+  private renderEndpointDescriptor_(
+      rawDataTreeRoot: CrTreeElement|CrTreeItemElement,
+      rawDataByteElement: HTMLElement, rawData: Uint8Array, offset: number,
+      indexEndpoint: number) {
     const parentClassName = `descriptor-endpoint-${indexEndpoint}`;
     const endpointItem =
         customTreeItem(`Endpoint ${indexEndpoint}`, parentClassName);
@@ -847,17 +783,12 @@
   /**
    * Renders a tree item to display length and type of unknown descriptor at
    * index indexUnknown.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the this descriptor.
-   * @param {number} indexUnknown
-   * @private
+   * @param originalOffset The start offset of the this descriptor.
    */
-  renderUnknownDescriptor_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-      indexUnknown) {
-    const length = rawData[originalOffset + STANDARD_DESCRIPTOR_LENGTH_OFFSET];
+  private renderUnknownDescriptor_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number, indexUnknown: number) {
+    const length = rawData[originalOffset + STANDARD_DESCRIPTOR_LENGTH_OFFSET]!;
     const parentClassName = `descriptor-unknown-${indexUnknown}`;
     const unknownItem =
         customTreeItem(`Unknown Descriptor ${indexUnknown}`, parentClassName);
@@ -883,8 +814,8 @@
     const rawDataByteElements = rawDataByteElement.querySelectorAll('span');
 
     for (; offset < originalOffset + length; offset++) {
-      rawDataByteElements[offset].classList.add(`field-offset-${offset}`);
-      rawDataByteElements[offset].classList.add(parentClassName);
+      rawDataByteElements[offset]!.classList.add(`field-offset-${offset}`);
+      rawDataByteElements[offset]!.classList.add(parentClassName);
     }
   }
 
@@ -892,11 +823,9 @@
    * Gets all the supported language codes of this device, and adds them as
    * autocompletions for the language code input area in the string descriptor
    * panel.
-   * @return {!Promise<!Array<number>>}
    */
-  async getAllLanguageCodes() {
-    /** @type {!UsbControlTransferParams} */
-    const usbControlTransferParams = {
+  async getAllLanguageCodes(): Promise<number[]> {
+    const usbControlTransferParams: UsbControlTransferParams = {
       type: UsbControlTransferType.STANDARD,
       recipient: UsbControlTransferRecipient.DEVICE,
       request: GET_DESCRIPTOR_REQUEST,
@@ -918,7 +847,7 @@
               'all supported languages.',
           this.rootElement_);
     } catch (e) {
-      showError(e.message, this.rootElement_);
+      showError((e as Error).message, this.rootElement_);
       // Stop rendering autocomplete datalist if failed to read the string
       // descriptor.
       return [];
@@ -927,6 +856,7 @@
     }
 
     const responseData = new Uint8Array(response.data.buffer);
+    assert(this.languageCodesListElement_);
     this.languageCodesListElement_.innerText = '';
 
     const optionAllElement = document.createElement('option');
@@ -952,15 +882,10 @@
   /**
    * Gets the string descriptor for the current device with the given index
    * and language code, and display it.
-   * @param {number} index
-   * @param {number} languageCode
-   * @param {!CrTreeItemElement=} treeItem
-   * @private
    */
-  async getStringDescriptorForLanguageCode_(
-      index, languageCode, treeItem = undefined) {
-    /** @type {!UsbControlTransferParams} */
-    const usbControlTransferParams = {
+  private async getStringDescriptorForLanguageCode_(
+      index: number, languageCode: number, treeItem?: CrTreeItemElement) {
+    const usbControlTransferParams: UsbControlTransferParams = {
       type: UsbControlTransferType.STANDARD,
       recipient: UsbControlTransferRecipient.DEVICE,
       request: GET_DESCRIPTOR_REQUEST,
@@ -979,11 +904,12 @@
               index}, language: ${parseLanguageCode(languageCode)}.`,
           this.rootElement_);
 
-      this.indexInput_.value = index;
+      assert(this.indexInput_);
+      this.indexInput_.value = index.toString();
       this.renderStandardDescriptor_(
           new Uint8Array(response.data.buffer), languageCode, treeItem);
     } catch (e) {
-      showError(e.message, this.rootElement_);
+      showError((e as Error).message, this.rootElement_);
     } finally {
       await this.usbDeviceProxy_.close();
     }
@@ -992,17 +918,12 @@
   /**
    * Renders string descriptor of current device with given index and language
    * code.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the string descriptor.
-   * @param {number=} languageCode
-   * @param {CrTreeItemElement=} treeItem
-   * @private
+   * @param offset The start offset of the string descriptor.
    */
-  renderStringDescriptorForLanguageCode_(
-      rawDataTreeRoot, rawDataByteElement, rawData, offset, languageCode = 0,
-      treeItem = undefined) {
+  private renderStringDescriptorForLanguageCode_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, offset: number, languageCode: number = 0,
+      treeItem?: CrTreeItemElement) {
     this.rootElement_.hidden = false;
 
     const languageStr = parseLanguageCode(languageCode);
@@ -1038,7 +959,7 @@
     rawDataTreeRoot.add(stringDescriptorItem);
     if (treeItem) {
       treeItem.add(customTreeItem(`${languageStr}: ${stringDescriptor}`));
-      treeItem.expanded = true;
+      treeItem.toggleAttribute('expanded', true);
     }
 
     renderRawDataTree(
@@ -1049,45 +970,45 @@
   /**
    * Gets string descriptor in all supported languages of current device with
    * given index.
-   * @param {number} index
-   * @param {CrTreeItemElement=} treeItem
-   * @private
    */
-  async getStringDescriptorForAllLanguages_(index, treeItem = undefined) {
+  private async getStringDescriptorForAllLanguages_(
+      index: number, treeItem?: CrTreeItemElement) {
     this.rootElement_.hidden = false;
 
-    this.indexInput_.value = index;
+    assert(this.indexInput_);
+    this.indexInput_.value = index.toString();
 
-    /** @type {!Array<number>} */
     const languageCodesList = await this.getAllLanguageCodes();
 
+    assert(treeItem);
     for (const languageCode of languageCodesList) {
       await this.getStringDescriptorForLanguageCode_(
-          index, languageCode, assert(treeItem));
+          index, languageCode, treeItem);
     }
   }
 
   /**
    * Initializes the string descriptor panel for autocomplete functionality.
-   * @param {string} tabId
    */
-  initialStringDescriptorPanel(tabId) {
+  initialStringDescriptorPanel(tabId: string) {
     // Binds the input area and datalist use each tab's unique id.
     this.rootElement_.querySelectorAll('input').forEach(
         el => el.setAttribute('list', `${el.getAttribute('list')}-${tabId}`));
     this.rootElement_.querySelectorAll('datalist')
         .forEach(el => el.id = `${el.id}-${tabId}`);
 
-    /** @type {!HTMLElement} */
-    const button = queryRequiredElement('button', this.rootElement_);
-    /** @type {!HTMLElement} */
-    this.indexInput_ = queryRequiredElement('#index-input', this.rootElement_);
-    /** @type {!HTMLElement} */
-    const languageCodeInput =
-        queryRequiredElement('#language-code-input', this.rootElement_);
+    const button = this.rootElement_.querySelector('button');
+    assert(button);
+    const indexInput =
+        this.rootElement_.querySelector<HTMLInputElement>('#index-input');
+    this.indexInput_ = indexInput;
+    const languageCodeInput = this.rootElement_.querySelector<HTMLInputElement>(
+        '#language-code-input');
+    assert(languageCodeInput);
 
     button.addEventListener('click', async () => {
       this.clearView();
+      assert(this.indexInput_);
       const index = Number.parseInt(this.indexInput_.value, 10);
       if (this.checkParamValid_(index, 'Index', 1, 255)) {
         if (languageCodeInput.value === 'All') {
@@ -1101,14 +1022,13 @@
       }
     });
 
-    /** @type {!Set<number>} */
-    this.stringDescriptorIndexes = new Set();
-    /** @type {!HTMLElement} */
+    this.stringDescriptorIndexes = new Set<number>();
     this.indexesListElement =
-        queryRequiredElement(`#indexes-${tabId}`, this.rootElement_);
-    /** @type {!HTMLElement} */
+        this.rootElement_.querySelector<HTMLElement>(`#indexes-${tabId}`);
+    assert(this.indexesListElement);
     this.languageCodesListElement_ =
-        queryRequiredElement(`#languages-${tabId}`, this.rootElement_);
+        this.rootElement_.querySelector<HTMLElement>(`#languages-${tabId}`);
+    assert(this.languageCodesListElement_);
   }
 
   /**
@@ -1117,8 +1037,7 @@
    * descriptor, and display it.
    */
   async getBosDescriptor() {
-    /** @type {!UsbControlTransferParams} */
-    const usbControlTransferParams = {
+    const usbControlTransferParams: UsbControlTransferParams = {
       type: UsbControlTransferType.STANDARD,
       recipient: UsbControlTransferRecipient.DEVICE,
       request: GET_DESCRIPTOR_REQUEST,
@@ -1149,7 +1068,7 @@
       await this.renderStandardDescriptor_(
           new Uint8Array(response.data.buffer));
     } catch (e) {
-      showError(e.message, this.rootElement_);
+      showError((e as Error).message, this.rootElement_);
     } finally {
       await this.usbDeviceProxy_.close();
     }
@@ -1158,13 +1077,11 @@
   /**
    * Renders a view to display Binary device Object Store (BOS) descriptor hex
    * data in both tree view and raw form.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the BOS descriptor.
-   * @private
+   * @param offset The start offset of the BOS descriptor.
    */
-  renderBosDescriptor_(rawDataTreeRoot, rawDataByteElement, rawData, offset) {
+  private renderBosDescriptor_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, offset: number) {
     const fields = [
       {
         'label': 'Length (should be 5): ',
@@ -1196,16 +1113,11 @@
   /**
    * Renders a view to display device capability descriptor hex data in both
    * tree view and raw form.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the BOS descriptor.
-   * @param {number} indexDevCapability
-   * @private
+   * @param offset The start offset of the BOS descriptor.
    */
-  async renderDeviceCapabilityDescriptor_(
-      rawDataTreeRoot, rawDataByteElement, rawData, offset,
-      indexDevCapability) {
+  private async renderDeviceCapabilityDescriptor_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, offset: number, indexDevCapability: number) {
     switch (rawData[offset + BOS_DESCRIPTOR_DEVICE_CAPABILITY_TYPE_OFFSET]) {
       case DEVICE_CAPABILITY_DESCRIPTOR_TYPE_PLATFORM_TYPE:
         if (isSameUuid(rawData, offset, WEB_USB_CAPABILITY_UUID)) {
@@ -1219,6 +1131,11 @@
               rawDataTreeRoot, rawDataByteElement, rawData, offset,
               indexDevCapability);
           break;
+        } else {
+          this.renderUnknownBosDescriptor_(
+              rawDataTreeRoot, rawDataByteElement, rawData, offset,
+              indexDevCapability);
+          break;
         }
       default:
         this.renderUnknownBosDescriptor_(
@@ -1230,16 +1147,12 @@
   /**
    * Renders a tree item to display WebUSB platform capability descriptor at
    * index indexWebUsb.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the WebUSB platform
+   * @param offset The start offset of the WebUSB platform
    *     capability descriptor.
-   * @param {number} indexWebUsb
-   * @private
    */
-  renderWebUsbPlatformDescriptor_(
-      rawDataTreeRoot, rawDataByteElement, rawData, offset, indexWebUsb) {
+  private renderWebUsbPlatformDescriptor_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, offset: number, indexWebUsb: number) {
     const parentClassName = `descriptor-webusb-${indexWebUsb}`;
     const webUsbItem = customTreeItem('WebUSB Descriptor', parentClassName);
     rawDataTreeRoot.add(webUsbItem);
@@ -1295,16 +1208,12 @@
   /**
    * Renders a tree item to display Microsoft OS 2.0 platform capability
    * descriptor at index indexMsOs20.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the Microsoft OS 2.0 platform
+   * @param offset The start offset of the Microsoft OS 2.0 platform
    *     capability descriptor.
-   * @param {number} indexMsOs20
-   * @private
    */
-  renderMsOs20PlatformDescriptor_(
-      rawDataTreeRoot, rawDataByteElement, rawData, offset, indexMsOs20) {
+  private renderMsOs20PlatformDescriptor_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, offset: number, indexMsOs20: number) {
     const parentClassName = `descriptor-ms-os-20-${indexMsOs20}`;
     const msOs20Item =
         customTreeItem(`Microsoft OS 2.0 Descriptor`, parentClassName);
@@ -1358,19 +1267,13 @@
   /**
    * Renders a tree item to display Microsoft OS 2.0 descriptor set
    * information at index indexMsOs20DescriptorSetInfo.
-   * @param {!CrTreeElement|!CrTreeItemElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The start offset of the Microsoft OS 2.0
+   * @param offset The start offset of the Microsoft OS 2.0
    *     set information structure.
-   * @param {number} indexMsOs20DescriptorSetInfo
-   * @param {number} indexMsOs20
-   * @return {number}
-   * @private
    */
-  renderMsOs20DescriptorSetInfo_(
-      rawDataTreeRoot, rawDataByteElement, rawData, offset,
-      indexMsOs20DescriptorSetInfo, indexMsOs20) {
+  private renderMsOs20DescriptorSetInfo_(
+      rawDataTreeRoot: CrTreeItemElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, offset: number, indexMsOs20DescriptorSetInfo: number,
+      indexMsOs20: number): number {
     const parentClassName =
         `descriptor-ms-os-20-set-info-${indexMsOs20DescriptorSetInfo}`;
     const msOs20SetInfoItem = customTreeItem(
@@ -1392,19 +1295,21 @@
         label: 'Vendor Code: ',
         size: 1,
         formatter: formatByte,
-        extraTreeItemFormatter: (rawData, offset, item, fieldLabel) =>
-            this.renderMsOs20DescriptorVendorSpecific_(
-                rawData, offset - MS_OS_20_VENDOR_CODE_ITEM_OFFSET, item,
-                fieldLabel),
+        extraTreeItemFormatter:
+            (rawData: Uint8Array, offset: number, item: CrTreeItemElement,
+             _fieldLabel: string) =>
+                this.renderMsOs20DescriptorVendorSpecific_(
+                    rawData, offset - MS_OS_20_VENDOR_CODE_ITEM_OFFSET, item),
       },
       {
         label: 'Alternate Enumeration Code: ',
         size: 1,
         formatter: formatByte,
-        extraTreeItemFormatter: (rawData, offset, item, fieldLabel) =>
-            this.renderMsOs20DescriptorSetAltEnum_(
-                rawData, offset - MS_OS_20_ALT_ENUM_CODE_ITEM_OFFSET, item,
-                fieldLabel),
+        extraTreeItemFormatter:
+            (rawData: Uint8Array, offset: number, item: CrTreeItemElement,
+             _fieldLabel: string) =>
+                this.renderMsOs20DescriptorSetAltEnum_(
+                    rawData, offset - MS_OS_20_ALT_ENUM_CODE_ITEM_OFFSET, item),
       },
     ];
 
@@ -1417,18 +1322,14 @@
   /**
    * Renders a tree item to display unknown device capability descriptor at
    * indexUnknownDevCapability
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the unknown device
+   * @param originalOffset The start offset of the unknown device
    *     capability descriptor.
-   * @param {number} indexUnknownDevCapability
-   * @private
    */
-  renderUnknownBosDescriptor_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-      indexUnknownDevCapability) {
-    const length = rawData[originalOffset + STANDARD_DESCRIPTOR_LENGTH_OFFSET];
+  private renderUnknownBosDescriptor_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number,
+      indexUnknownDevCapability: number) {
+    const length = rawData[originalOffset + STANDARD_DESCRIPTOR_LENGTH_OFFSET]!;
 
     const parentClassName =
         `descriptor-unknownbos-${indexUnknownDevCapability}`;
@@ -1461,28 +1362,26 @@
     const rawDataByteElements = rawDataByteElement.querySelectorAll('span');
 
     for (; offset < originalOffset + length; offset++) {
-      rawDataByteElements[offset].classList.add(`field-offset-${offset}`);
-      rawDataByteElements[offset].classList.add(parentClassName);
+      rawDataByteElements[offset]!.classList.add(`field-offset-${offset}`);
+      rawDataByteElements[offset]!.classList.add(parentClassName);
     }
   }
 
   /**
    * Gets the URL Descriptor, renders a URL descriptor item and adds it to
    * the URL descriptor index item.
-   * @param {!Uint8Array} rawData
-   * @param {number} offset The offset of the WebUSB descriptor.
-   * @param {!CrTreeItemElement} item The URL descriptor index item.
-   * @private
+   * @param offset The offset of the WebUSB descriptor.
+   * @param item The URL descriptor index item.
    */
-  async getUrlDescriptor_(rawData, offset, item) {
+  private async getUrlDescriptor_(
+      rawData: Uint8Array, offset: number, item: CrTreeItemElement) {
     // The second to last byte is the vendor code used to query URL
     // descriptor. Last byte is index of url descriptor. These are defined by
     // the WebUSB specification: http://wicg.github.io/webusb/
-    const vendorCode = rawData[offset + WEB_USB_VENDOR_CODE_OFFSET];
-    const urlIndex = rawData[offset + WEB_USB_URL_DESCRIPTOR_INDEX_OFFSET];
+    const vendorCode = rawData[offset + WEB_USB_VENDOR_CODE_OFFSET]!;
+    const urlIndex = rawData[offset + WEB_USB_URL_DESCRIPTOR_INDEX_OFFSET]!;
 
-    /** @type {!UsbControlTransferParams} */
-    const usbControlTransferParams = {
+    const usbControlTransferParams: UsbControlTransferParams = {
       recipient: UsbControlTransferRecipient.DEVICE,
       // These constants are defined by the WebUSB specification:
       // http://wicg.github.io/webusb/
@@ -1503,7 +1402,7 @@
           urlResponse.status, 'Failed to read the device URL descriptor.',
           this.rootElement_);
 
-      let url;
+      let url: string = '';
       // URL Prefixes are defined by Chapter 4.3.1 of the WebUSB
       // specification: http://wicg.github.io/webusb/
       switch (urlResponse.data.buffer[2]) {
@@ -1527,10 +1426,9 @@
       item.add(landingPageItem);
       item.expanded = true;
     } catch (e) {
-      showError(e.message, this.rootElement_);
+      showError((e as Error).message, this.rootElement_);
       // Stops parsing to string format URL if failed to read the URL
       // descriptor.
-      return '';
     } finally {
       await this.usbDeviceProxy_.close();
     }
@@ -1538,13 +1436,11 @@
 
   /**
    * Gets the Microsoft OS 2.0 Descriptor vendor-specific descriptor.
-   * @param {number} vendorCode
-   * @return {!Promise<!Uint8Array>}
-   * @private
    */
-  async getMsOs20DescriptorSet_(vendorCode, msOs20DescriptorSetLength) {
-    /** @type {!UsbControlTransferParams} */
-    const usbControlTransferParams = {
+  private async getMsOs20DescriptorSet_(
+      vendorCode: number,
+      msOs20DescriptorSetLength: number): Promise<Uint8Array> {
+    const usbControlTransferParams: UsbControlTransferParams = {
       recipient: UsbControlTransferRecipient.DEVICE,
       // These constants are defined by Microsoft OS 2.0 Descriptors
       // Specification (July, 2018).
@@ -1567,7 +1463,7 @@
           'Failed to read the Microsoft OS 2.0 descriptor set.',
           this.rootElement_);
     } catch (e) {
-      showError(e.message, this.rootElement_);
+      showError((e as Error).message, this.rootElement_);
       // Returns an empty array if failed to read the Microsoft OS 2.0
       // descriptor set.
       return new Uint8Array(0);
@@ -1580,13 +1476,10 @@
 
   /**
    * Sends the Microsoft OS 2.0 Descriptor set alternate enumeration command.
-   * @param {number} vendorCode
-   * @param {number} altEnumCode
-   * @private
    */
-  async sendMsOs20DescriptorSetAltEnumCommand_(vendorCode, altEnumCode) {
-    /** @type {!UsbControlTransferParams} */
-    const usbControlTransferParams = {
+  private async sendMsOs20DescriptorSetAltEnumCommand_(
+      vendorCode: number, altEnumCode: number) {
+    const usbControlTransferParams: UsbControlTransferParams = {
       recipient: UsbControlTransferRecipient.DEVICE,
       // These constants are defined by Microsoft OS 2.0 Descriptors
       // Specification (July, 2018).
@@ -1610,7 +1503,7 @@
               'alternate enumeration set.',
           this.rootElement_);
     } catch (e) {
-      showError(e.message, this.rootElement_);
+      showError((e as Error).message, this.rootElement_);
     } finally {
       await this.usbDeviceProxy_.close();
     }
@@ -1619,15 +1512,11 @@
   /**
    * Renders a view to display Microsoft OS 2.0 Descriptor Set hex data in
    * both tree view and raw form.
-   * @param {!Uint8Array} msOs20RawData
-   * @private
    */
-  renderMsOs20DescriptorSet_(msOs20RawData) {
+  private renderMsOs20DescriptorSet_(msOs20RawData: Uint8Array) {
     const displayElement = addNewDescriptorDisplayElement(
         this.rootElement_, 'Microsoft OS 2.0 Descriptor Set');
-    /** @type {!CrTreeElement} */
     const rawDataTreeRoot = displayElement.rawDataTreeRoot;
-    /** @type {!HTMLElement} */
     const rawDataByteElement = displayElement.rawDataByteElement;
     renderRawDataBytes(rawDataByteElement, msOs20RawData);
 
@@ -1708,16 +1597,12 @@
 
   /**
    * Renders a tree item to display Microsoft OS 2.0 descriptor set header.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the Microsoft OS 2.0
+   * @param originalOffset The start offset of the Microsoft OS 2.0
    *     descriptor set header.
-   * @return {number}
-   * @private
    */
-  renderMsOs20SetHeader_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset) {
+  private renderMsOs20SetHeader_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number): number {
     const data = new DataView(rawData.buffer);
     const length = data.getUint16(
         originalOffset + MS_OS_20_DESCRIPTOR_LENGTH_OFFSET, true);
@@ -1762,18 +1647,13 @@
   /**
    * Renders a tree item to display Microsoft OS 2.0 configuration subset
    * header.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the Microsoft OS 2.0
+   * @param originalOffset The start offset of the Microsoft OS 2.0
    *     configuration subset header.
-   * @param {number} indexMsOs20Descriptor
-   * @return {number}
-   * @private
    */
-  renderMsOs20ConfigurationSubsetHeader_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-      indexMsOs20Descriptor) {
+  private renderMsOs20ConfigurationSubsetHeader_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number,
+      indexMsOs20Descriptor: number): number {
     const parentClassName =
         `descriptor-ms-os-20-subdescriptor-${indexMsOs20Descriptor}`;
     const item = customTreeItem(
@@ -1828,18 +1708,13 @@
 
   /**
    * Renders a tree item to display Microsoft OS 2.0 function subset header.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the Microsoft OS 2.0
+   * @param originalOffset The start offset of the Microsoft OS 2.0
    *     function subset header.
-   * @param {number} indexMsOs20Descriptor
-   * @return {number}
-   * @private
    */
-  renderMsOs20FunctionSubsetHeader_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-      indexMsOs20Descriptor) {
+  private renderMsOs20FunctionSubsetHeader_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number,
+      indexMsOs20Descriptor: number): number {
     const parentClassName =
         `descriptor-ms-os-20-subdescriptor-${indexMsOs20Descriptor}`;
     const item = customTreeItem(
@@ -1893,18 +1768,13 @@
 
   /**
    * Renders a tree item to display Microsoft OS 2.0 compatible ID Descriptor.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the Microsoft OS 2.0
+   * @param originalOffset The start offset of the Microsoft OS 2.0
    *     compatible ID descriptor.
-   * @param {number} indexMsOs20Descriptor
-   * @return {number}
-   * @private
    */
-  renderMsOs20FeatureCompatibleId_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-      indexMsOs20Descriptor) {
+  private renderMsOs20FeatureCompatibleId_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number,
+      indexMsOs20Descriptor: number): number {
     const parentClassName =
         `descriptor-ms-os-20-subdescriptor-${indexMsOs20Descriptor}`;
     const item = customTreeItem(
@@ -1954,18 +1824,13 @@
   /**
    * Renders a tree item to display Microsoft OS 2.0 registry property
    * descriptor.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the Microsoft OS 2.0
+   * @param originalOffset The start offset of the Microsoft OS 2.0
    *     registry property descriptor.
-   * @param {number} indexMsOs20Descriptor
-   * @return {number}
-   * @private
    */
-  renderMsOs20FeatureRegistryProperty_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-      indexMsOs20Descriptor) {
+  private renderMsOs20FeatureRegistryProperty_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number,
+      indexMsOs20Descriptor: number): number {
     const parentClassName =
         `descriptor-ms-os-20-subdescriptor-${indexMsOs20Descriptor}`;
     const item = customTreeItem(
@@ -2007,10 +1872,12 @@
         label: 'Property Name: ',
         size: propertyNameLength,
         formatter: formatUnknown,
-        extraTreeItemFormatter: (rawData, offset, item, fieldLabel) =>
-            this.renderFeatureRegistryPropertyDataItem_(
-                rawData, offset, item, fieldLabel,
-                featureRegistryPropertyDataType, propertyNameLength),
+        extraTreeItemFormatter:
+            (rawData: Uint8Array, offset: number, item: CrTreeItemElement,
+             fieldLabel: string) =>
+                this.renderFeatureRegistryPropertyDataItem_(
+                    rawData, offset, item, fieldLabel,
+                    featureRegistryPropertyDataType, propertyNameLength),
       },
     ];
 
@@ -2030,10 +1897,12 @@
           label: 'Property Data: ',
           size: propertyDataLength,
           formatter: formatUnknown,
-          extraTreeItemFormatter: (rawData, offset, item, fieldLabel) =>
-              this.renderFeatureRegistryPropertyDataItem_(
-                  rawData, offset, item, fieldLabel,
-                  featureRegistryPropertyDataType, propertyDataLength),
+          extraTreeItemFormatter:
+              (rawData: Uint8Array, offset: number, item: CrTreeItemElement,
+               fieldLabel: string) =>
+                  this.renderFeatureRegistryPropertyDataItem_(
+                      rawData, offset, item, fieldLabel,
+                      featureRegistryPropertyDataType, propertyDataLength),
         },
       ];
       offset = renderRawDataTree(
@@ -2054,18 +1923,13 @@
   /**
    * Renders a tree item to display Microsoft OS 2.0 minimum USB resume time
    * descriptor.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the Microsoft OS 2.0
+   * @param originalOffset The start offset of the Microsoft OS 2.0
    *     minimum USB resume time descriptor.
-   * @param {number} indexMsOs20Descriptor
-   * @return {number}
-   * @private
    */
-  renderMsOs20FeatureMinResumeTime_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-      indexMsOs20Descriptor) {
+  private renderMsOs20FeatureMinResumeTime_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number,
+      indexMsOs20Descriptor: number): number {
     const parentClassName =
         `descriptor-ms-os-20-subdescriptor-${indexMsOs20Descriptor}`;
     const item = customTreeItem(
@@ -2114,18 +1978,13 @@
 
   /**
    * Renders a tree item to display Microsoft OS 2.0 model ID descriptor.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the Microsoft OS 2.0
+   * @param originalOffset The start offset of the Microsoft OS 2.0
    *     model ID descriptor.
-   * @param {number} indexMsOs20Descriptor
-   * @return {number}
-   * @private
    */
-  renderMsOs20FeatureModelId_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-      indexMsOs20Descriptor) {
+  private renderMsOs20FeatureModelId_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number,
+      indexMsOs20Descriptor: number): number {
     const parentClassName =
         `descriptor-ms-os-20-subdescriptor-${indexMsOs20Descriptor}`;
     const item =
@@ -2170,18 +2029,13 @@
   /**
    * Renders a tree item to display Microsoft OS 2.0 Common Class Generic
    * Parent (CCGP) device descriptor.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the Microsoft OS 2.0
+   * @param originalOffset The start offset of the Microsoft OS 2.0
    *     CCGP device descriptor.
-   * @param {number} indexMsOs20Descriptor
-   * @return {number}
-   * @private
    */
-  renderMsOs20FeatureCcgpDevice_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-      indexMsOs20Descriptor) {
+  private renderMsOs20FeatureCcgpDevice_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number,
+      indexMsOs20Descriptor: number): number {
     const parentClassName =
         `descriptor-ms-os-20-subdescriptor-${indexMsOs20Descriptor}`;
     const item = customTreeItem(
@@ -2223,18 +2077,13 @@
   /**
    * Renders a tree item to display Microsoft OS 2.0 vendor revision
    * descriptor.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the Microsoft OS 2.0
+   * @param originalOffset The start offset of the Microsoft OS 2.0
    *     vendor revision descriptor.
-   * @param {number} indexMsOs20Descriptor
-   * @return {number}
-   * @private
    */
-  renderMsOs20FeatureVendorRevision_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-      indexMsOs20Descriptor) {
+  private renderMsOs20FeatureVendorRevision_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number,
+      indexMsOs20Descriptor: number): number {
     const parentClassName =
         `descriptor-ms-os-20-subdescriptor-${indexMsOs20Descriptor}`;
     const item = customTreeItem(
@@ -2278,18 +2127,13 @@
 
   /**
    * Renders a tree item to display an unknown Microsoft OS 2.0 descriptor.
-   * @param {!CrTreeElement} rawDataTreeRoot
-   * @param {!HTMLElement} rawDataByteElement
-   * @param {!Uint8Array} rawData
-   * @param {number} originalOffset The start offset of the unknown Microsoft
+   * @param originalOffset The start offset of the unknown Microsoft
    *     OS 2.0 descriptor.
-   * @param {number} indexDescriptor
-   * @return {number}
-   * @private
    */
-  renderUnknownMsOs20DescriptorDescriptor_(
-      rawDataTreeRoot, rawDataByteElement, rawData, originalOffset,
-      indexDescriptor) {
+  private renderUnknownMsOs20DescriptorDescriptor_(
+      rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement,
+      rawData: Uint8Array, originalOffset: number,
+      indexDescriptor: number): number {
     const parentClassName =
         `descriptor-ms-os-20-subdescriptor-${indexDescriptor}`;
     const item = customTreeItem(
@@ -2319,7 +2163,7 @@
     const rawDataByteElements = rawDataByteElement.querySelectorAll('span');
 
     for (; offset < originalOffset + length; offset++) {
-      rawDataByteElements[offset].classList.add(
+      rawDataByteElements[offset]!.classList.add(
           `field-offset-${offset}`, parentClassName);
     }
 
@@ -2335,12 +2179,10 @@
 
   /**
    * Gets response of the given request.
-   * @param {!UsbControlTransferParams} usbControlTransferParams
-   * @param {number} length
-   * @param {string} direction
-   * @private
    */
-  async sendTestingRequest_(usbControlTransferParams, length, direction) {
+  private async sendTestingRequest_(
+      usbControlTransferParams: UsbControlTransferParams, length: number,
+      direction: string) {
     try {
       await this.usbDeviceProxy_.open();
 
@@ -2351,7 +2193,9 @@
             response.status, 'Failed to send request.', this.rootElement_);
         this.renderTestingData_(new Uint8Array(response.data.buffer));
       } else if (direction === 'Host-to-Device') {
-        const dataString = this.rootElement_.querySelector('textarea').value;
+        const textarea = this.rootElement_.querySelector('textarea');
+        assert(textarea);
+        const dataString = textarea.value;
 
         const data = [];
         for (let i = 0; i < dataString.length; i += 2) {
@@ -2365,7 +2209,7 @@
             response.status, 'Failed to send request.', this.rootElement_);
       }
     } catch (e) {
-      showError(e.message, this.rootElement_);
+      showError((e as Error).message, this.rootElement_);
       return;
     } finally {
       await this.usbDeviceProxy_.close();
@@ -2374,14 +2218,11 @@
 
   /**
    * Renders a view to display response data in hex format.
-   * @param {!Uint8Array} rawData
-   * @private
    */
-  async renderTestingData_(rawData) {
+  private async renderTestingData_(rawData: Uint8Array) {
     const displayElement = addNewDescriptorDisplayElement(this.rootElement_);
     const rawDataTreeRoot = displayElement.rawDataTreeRoot;
-    /** @type {!HTMLElement} */ (rawDataTreeRoot).style.display = 'none';
-    /** @type {!HTMLElement} */
+    rawDataTreeRoot.style.display = 'none';
     const rawDataByteElement = displayElement.rawDataByteElement;
     renderRawDataBytes(rawDataByteElement, rawData);
   }
@@ -2394,11 +2235,12 @@
         'Warning: This tool can send arbitrary commands to the device. ' +
             'Invalid commands may cause unexpected results.',
         this.rootElement_);
-    const inputTableRows =
-        this.rootElement_.querySelector('tbody').querySelectorAll('tr');
-    const buttons =
-        this.rootElement_.querySelector('tbody').querySelectorAll('button');
+    const tbody = this.rootElement_.querySelector('tbody');
+    assert(tbody);
+    const inputTableRows = tbody.querySelectorAll('tr');
+    const buttons = tbody.querySelectorAll('button');
     const dataInputArea = this.rootElement_.querySelector('textarea');
+    assert(dataInputArea);
     dataInputArea.addEventListener('keypress', () => {
       const index = dataInputArea.selectionStart;
       dataInputArea.value = dataInputArea.value.substring(0, index) +
@@ -2407,26 +2249,30 @@
     });
 
     const testingToolPanelInputTypeSelector =
-        this.rootElement_.querySelector('#input-type');
+        this.rootElement_.querySelector<HTMLSelectElement>('#input-type');
+    assert(testingToolPanelInputTypeSelector);
     testingToolPanelInputTypeSelector.addEventListener('change', () => {
       this.clearView();
       const index = testingToolPanelInputTypeSelector.selectedIndex;
       inputTableRows.forEach(row => row.hidden = true);
-      const rowAtIndex = assertInstanceof(inputTableRows[index], HTMLElement);
+      const rowAtIndex = inputTableRows[index];
+      assert(rowAtIndex);
       rowAtIndex.hidden = false;
 
       const direction = getRequestTypeDirection(rowAtIndex, index);
       const length = getRequestLength(rowAtIndex, index);
-      this.rootElement_.querySelector('#data-input-area').hidden =
-          (direction !== 'Host-to-Device');
+      const area =
+          this.rootElement_.querySelector<HTMLElement>('#data-input-area');
+      assert(area);
+      area.hidden = (direction !== 'Host-to-Device');
       dataInputArea.value = '00'.repeat(length);
       dataInputArea.maxLength = length * 2;
     });
 
 
     inputTableRows.forEach((el, i) => {
-      const inputTableRow = assertInstanceof(el, HTMLElement);
-      let directionInputElement;
+      const inputTableRow = el;
+      let directionInputElement: HTMLElement|null = null;
       switch (i) {
         case INPUT_TYPE_DECIMAL_WITH_DROPDOWN:
           directionInputElement =
@@ -2437,13 +2283,17 @@
               inputTableRow.querySelector('#query-request-type');
           break;
       }
+      assert(directionInputElement);
       directionInputElement.addEventListener('change', () => {
-        this.rootElement_.querySelector('#data-input-area').hidden =
+        const area =
+            this.rootElement_.querySelector<HTMLElement>('#data-input-area');
+        assert(area);
+        area.hidden =
             (getRequestTypeDirection(inputTableRow, i) !== 'Host-to-Device');
       });
 
-      inputTableRow.querySelector('#query-length')
-          .addEventListener('blur', () => {
+      inputTableRow.querySelector('#query-length')!.addEventListener(
+          'blur', () => {
             const length = getRequestLength(inputTableRow, i);
             dataInputArea.value = '00'.repeat(length);
             dataInputArea.maxLength = length * 2;
@@ -2454,7 +2304,8 @@
       button.addEventListener('click', () => {
         this.clearView();
 
-        const row = assertInstanceof(inputTableRows[i], HTMLElement);
+        const row = inputTableRows[i];
+        assert(row);
         const direction = getRequestTypeDirection(row, i);
         const type = getRequestType(row, i);
         const recipient = getRequestTypeRecipient(row, i);
@@ -2471,10 +2322,11 @@
             this.checkParamValid_(value, 'wValue', 0, 65535) &&
             this.checkParamValid_(index, 'wIndex', 0, 65535) &&
             this.checkParamValid_(dataLength, 'Length', 0, 65535)) {
-          /** @type {!UsbControlTransferParams} */
-          const usbControlTransferParams = {
-            type: UsbControlTransferType[type],
-            recipient: UsbControlTransferRecipient[recipient],
+          const usbControlTransferParams: UsbControlTransferParams = {
+            type: (UsbControlTransferType as {[key: string]: number})[type]!,
+            recipient:
+                (UsbControlTransferRecipient as
+                 {[key: string]: number})[recipient]!,
             request,
             value,
             index,
@@ -2488,14 +2340,10 @@
 
   /**
    * Checks if the user input is a valid number.
-   * @param {number} paramValue
-   * @param {string} paramName
-   * @param {number} min
-   * @param {number} max
-   * @return {boolean}
-   * @private
    */
-  checkParamValid_(paramValue, paramName, min, max) {
+  private checkParamValid_(
+      paramValue: number, paramName: string, min: number,
+      max: number): boolean {
     if (Number.isNaN(paramValue) || paramValue < min || paramValue > max) {
       showError(`Invalid ${paramName}.`, this.rootElement_);
       return false;
@@ -2505,13 +2353,10 @@
 
   /**
    * Checks if the user input for a enum field is valid.
-   * @param {string} enumString
-   * @param {string} paramName
-   * @param {!Object} enumObject
-   * @return {boolean}
-   * @private
    */
-  checkEnumParamValid_(enumString, paramName, enumObject) {
+  private checkEnumParamValid_(
+      enumString: string|number, paramName: string,
+      enumObject: {[key: string]: number|string}): boolean {
     if (enumObject[enumString] !== undefined) {
       return true;
     }
@@ -2522,17 +2367,19 @@
 
 /**
  * Get the USB control transfer type.
- * @param {!HTMLElement} inputRow
- * @param {number} inputType
- * @return {string}
  */
-function getRequestType(inputRow, inputType) {
+function getRequestType(inputRow: HTMLElement, inputType: number): string {
   switch (inputType) {
     case INPUT_TYPE_DECIMAL_WITH_DROPDOWN:
-      return queryRequiredElement('#transfer-type', inputRow).value;
+      const select =
+          inputRow.querySelector<HTMLSelectElement>('#transfer-type');
+      assert(select);
+      return select.value;
     case INPUT_TYPE_HEX_BYTE:
-      const value = Number.parseInt(
-          queryRequiredElement('#query-request-type', inputRow).value, 16);
+      const input =
+          inputRow.querySelector<HTMLInputElement>('#query-request-type');
+      assert(input);
+      const value = Number.parseInt(input.value, 16);
       switch (value >> 5 & 0x03) {
         case 0:
           return 'STANDARD';
@@ -2541,6 +2388,7 @@
         case 2:
           return 'VENDOR';
       }
+      return '';
     default:
       return '';
   }
@@ -2548,17 +2396,20 @@
 
 /**
  * Get the USB control transfer recipient.
- * @param {!HTMLElement} inputRow
- * @param {number} inputType
- * @return {string}
  */
-function getRequestTypeRecipient(inputRow, inputType) {
+function getRequestTypeRecipient(
+    inputRow: HTMLElement, inputType: number): string {
   switch (inputType) {
     case INPUT_TYPE_DECIMAL_WITH_DROPDOWN:
-      return queryRequiredElement('#transfer-recipient', inputRow).value;
+      const select =
+          inputRow.querySelector<HTMLSelectElement>('#transfer-recipient');
+      assert(select);
+      return select.value;
     case INPUT_TYPE_HEX_BYTE:
-      const value = Number.parseInt(
-          queryRequiredElement('#query-request-type', inputRow).value, 16);
+      const input =
+          inputRow.querySelector<HTMLInputElement>('#query-request-type');
+      assert(input);
+      const value = Number.parseInt(input.value, 16);
       switch (value & 0x1F) {
         case 0:
           return 'DEVICE';
@@ -2569,6 +2420,7 @@
         case 3:
           return 'OTHER';
       }
+      return '';
     default:
       return '';
   }
@@ -2577,135 +2429,107 @@
 /**
  * Get the USB control transfer direction. 0 for device-to-host, 1 for
  * host-to-device.
- * @param {!HTMLElement} inputRow
- * @param {number} inputType
- * @return {string}
  */
-function getRequestTypeDirection(inputRow, inputType) {
+function getRequestTypeDirection(
+    inputRow: HTMLElement, inputType: number): string {
   switch (inputType) {
     case INPUT_TYPE_DECIMAL_WITH_DROPDOWN:
-      return queryRequiredElement('#transfer-direction', inputRow).value;
+      const select =
+          inputRow.querySelector<HTMLSelectElement>('#transfer-direction');
+      assert(select);
+      return select.value;
     case INPUT_TYPE_HEX_BYTE:
-      const value = Number.parseInt(
-          queryRequiredElement('#query-request-type', inputRow).value, 16);
+      const input =
+          inputRow.querySelector<HTMLInputElement>('#query-request-type');
+      assert(input);
+      const value = Number.parseInt(input.value, 16);
       switch (value >> 7) {
         case CONTROL_TRANSFER_DIRECTION_HOST_TO_DEVICE:
           return 'Host-to-Device';
         case CONTROL_TRANSFER_DIRECTION_DEVICE_TO_HOST:
           return 'Device-to-Host';
       }
+      return 'Device-to-Host';
     default:
       return 'Device-to-Host';
   }
 }
 
-/**
- * Get the USB control transfer request code.
- * @param {!HTMLElement} inputRow
- * @param {number} inputType
- * @return {number}
- */
-function getRequestCode(inputRow, inputType) {
+function getDecimalOrHex(
+    inputRow: HTMLElement, inputType: number, selector: string): number {
+  const input = inputRow.querySelector<HTMLInputElement>(selector);
   switch (inputType) {
     case INPUT_TYPE_DECIMAL_WITH_DROPDOWN:
-      return Number.parseInt(
-          queryRequiredElement('#query-request', inputRow).value, 10);
+      assert(input);
+      return Number.parseInt(input.value, 10);
     case INPUT_TYPE_HEX_BYTE:
-      return Number.parseInt(
-          queryRequiredElement('#query-request', inputRow).value, 16);
+      assert(input);
+      return Number.parseInt(input.value, 16);
     default:
       return Number.NaN;
   }
 }
 
 /**
+ * Get the USB control transfer request code.
+ */
+function getRequestCode(inputRow: HTMLElement, inputType: number): number {
+  return getDecimalOrHex(inputRow, inputType, '#query-request');
+}
+
+/**
  * Get the value of USB control transfer request wValue field.
- * @param {!HTMLElement} inputRow
- * @param {number} inputType
- * @return {number}
  */
-function getRequestValue(inputRow, inputType) {
-  switch (inputType) {
-    case INPUT_TYPE_DECIMAL_WITH_DROPDOWN:
-      return Number.parseInt(
-          queryRequiredElement('#query-value', inputRow).value, 10);
-    case INPUT_TYPE_HEX_BYTE:
-      return Number.parseInt(
-          queryRequiredElement('#query-value', inputRow).value, 16);
-    default:
-      return Number.NaN;
-  }
+function getRequestValue(inputRow: HTMLElement, inputType: number): number {
+  return getDecimalOrHex(inputRow, inputType, '#query-value');
 }
 
 /**
  * Get the value of USB control transfer request wIndex field.
- * @param {!HTMLElement} inputRow
- * @param {number} inputType
- * @return {number}
  */
-function getRequestIndex(inputRow, inputType) {
-  switch (inputType) {
-    case INPUT_TYPE_DECIMAL_WITH_DROPDOWN:
-      return Number.parseInt(
-          queryRequiredElement('#query-index', inputRow).value, 10);
-    case INPUT_TYPE_HEX_BYTE:
-      return Number.parseInt(
-          queryRequiredElement('#query-index', inputRow).value, 16);
-    default:
-      return Number.NaN;
-  }
+function getRequestIndex(inputRow: HTMLElement, inputType: number): number {
+  return getDecimalOrHex(inputRow, inputType, '#query-index');
 }
 
 /**
  * Get the length of the data transferred during USB control transfer.
- * @param {!HTMLElement} inputRow
- * @param {number} inputType
- * @return {number}
  */
-function getRequestLength(inputRow, inputType) {
-  switch (inputType) {
-    case INPUT_TYPE_DECIMAL_WITH_DROPDOWN:
-      return Number.parseInt(
-          queryRequiredElement('#query-length', inputRow).value, 10);
-    case INPUT_TYPE_HEX_BYTE:
-      return Number.parseInt(
-          queryRequiredElement('#query-length', inputRow).value, 16);
-    default:
-      return Number.NaN;
-  }
+function getRequestLength(inputRow: HTMLElement, inputType: number): number {
+  return getDecimalOrHex(inputRow, inputType, '#query-length');
 }
 
 /**
  * Adds a display area which contains a tree view and a byte view.
- * @param {!HTMLElement} rootElement
- * @param {string=} descriptorPanelTitle
- * @return {{rawDataTreeRoot:!CrTreeElement,rawDataByteElement:!HTMLElement}}
  */
 function addNewDescriptorDisplayElement(
-    rootElement, descriptorPanelTitle = undefined) {
-  const descriptorPanelTemplate = queryRequiredElement(
-      '#descriptor-panel-template',
-      /** @type {!DocumentFragment} */ (rootElement.getRootNode()));
+    rootElement: HTMLElement, descriptorPanelTitle?: string):
+    {rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement} {
+  const descriptorPanelTemplate =
+      (rootElement.getRootNode() as DocumentFragment | HTMLElement)
+          .querySelector<HTMLTemplateElement>('#descriptor-panel-template');
+  assert(descriptorPanelTemplate);
 
-  const descriptorPanelClone = /** @type {!HTMLElement} */
-      (document.importNode(descriptorPanelTemplate.content, true));
+  const descriptorPanelClone =
+      document.importNode(descriptorPanelTemplate.content, true);
 
   const rawDataTreeRoot =
-      /** @type {!CrTreeElement} */ (
-          queryRequiredElement('.raw-data-tree-view', descriptorPanelClone));
-  /** @type {!HTMLElement} */
+      descriptorPanelClone.querySelector<CrTreeElement>('.raw-data-tree-view');
+  assert(rawDataTreeRoot);
   const rawDataByteElement =
-      queryRequiredElement('.raw-data-byte-view', descriptorPanelClone);
+      descriptorPanelClone.querySelector<HTMLElement>('.raw-data-byte-view');
+  assert(rawDataByteElement);
 
   rawDataTreeRoot.detail = {payload: {}, children: {}};
 
   if (descriptorPanelTitle) {
-    const descriptorPanelTitleTemplate = queryRequiredElement(
-        '#descriptor-panel-title',
-        /** @type {!DocumentFragment} */ (rootElement.getRootNode()));
+    const descriptorPanelTitleTemplate =
+        (rootElement.getRootNode() as DocumentFragment | HTMLElement)
+            .querySelector<HTMLTemplateElement>('#descriptor-panel-title');
+    assert(descriptorPanelTitleTemplate);
     const clone =
         document.importNode(descriptorPanelTitleTemplate.content, true)
             .querySelector('descriptorpaneltitle');
+    assert(clone);
     clone.textContent = descriptorPanelTitle;
     rootElement.appendChild(clone);
   }
@@ -2715,10 +2539,8 @@
 
 /**
  * Shows an error message.
- * @param {string} message
- * @param {!HTMLElement} rootElement
  */
-function showError(message, rootElement) {
+function showError(message: string, rootElement: HTMLElement) {
   const errorElement = document.createElement('error');
   errorElement.textContent = message;
   rootElement.prepend(errorElement);
@@ -2726,10 +2548,8 @@
 
 /**
  * Shows a warning message.
- * @param {string} message
- * @param {!HTMLElement} rootElement
  */
-function showWarn(message, rootElement) {
+function showWarn(message: string, rootElement: HTMLElement) {
   const warnElement = document.createElement('warn');
   warnElement.textContent = message;
   rootElement.prepend(warnElement);
@@ -2737,13 +2557,10 @@
 
 /**
  * Renders a customized TreeItem with the given content and class name.
- * @param {string} itemLabel
- * @param {string=} className
- * @return {!CrTreeItemElement}
  */
-function customTreeItem(itemLabel, className = undefined) {
-  const item =
-      /** @type {CrTreeItemElement} */ (document.createElement('cr-tree-item'));
+function customTreeItem(
+    itemLabel: string, className?: string): CrTreeItemElement {
+  const item = document.createElement('cr-tree-item');
   item.label = itemLabel;
   if (className) {
     item.classList.add(className);
@@ -2753,24 +2570,21 @@
 
 /**
  * Adds function for mapping between two views.
- * @param {!CrTreeElement} rawDataTreeRoot
- * @param {!HTMLElement} rawDataByteElement
  */
-function addMappingAction(rawDataTreeRoot, rawDataByteElement) {
+function addMappingAction(
+    rawDataTreeRoot: CrTreeElement, rawDataByteElement: HTMLElement) {
   // Highlights the byte(s) that hovered in the tree.
-  const items = rawDataTreeRoot.items;
-
-  function mapElement(el) {
+  function mapElement(el: CrTreeItemElement) {
     const classList = el.classList;
     // classList[0] is 'tree-row'. classList[1] of tree item for fields
     // starts with 'field-offset-', and classList[1] of tree item for
     // descriptors (ie. endpoint descriptor) is descriptor type and index.
-    const fieldOffsetOrDescriptorClass = classList[0];
+    const fieldOffsetOrDescriptorClass = classList[0]!;
     assert(
         fieldOffsetOrDescriptorClass.startsWith('field-offset-') ||
         fieldOffsetOrDescriptorClass.startsWith('descriptor-'));
 
-    el.rowElement.addEventListener('pointerenter', (event) => {
+    el.rowElement.addEventListener('pointerenter', (event: MouseEvent) => {
       rawDataByteElement.querySelectorAll(`.${fieldOffsetOrDescriptorClass}`)
           .forEach((el) => el.classList.add('hovered-field'));
       event.stopPropagation();
@@ -2781,8 +2595,8 @@
           .forEach((el) => el.classList.remove('hovered-field'));
     });
 
-    el.rowElement.addEventListener('click', (event) => {
-      if (event.target.className !== 'expand-icon') {
+    el.rowElement.addEventListener('click', (event: MouseEvent) => {
+      if ((event.target as HTMLElement).className !== 'expand-icon') {
         // Clears all the selected elements before select another.
         rawDataByteElement.querySelectorAll('.raw-data-byte-view span')
             .forEach((el) => el.classList.remove('selected-field'));
@@ -2792,10 +2606,10 @@
       }
     });
 
-    el.items.forEach(item => mapElement(item));
+    el.items.forEach(item => mapElement(item as CrTreeItemElement));
   }
 
-  rawDataTreeRoot.items.forEach(item => mapElement(item));
+  rawDataTreeRoot.items.forEach(item => mapElement(item as CrTreeItemElement));
 
   // Selects the tree item that displays the byte hovered in the raw view.
   const rawDataByteElements = rawDataByteElement.querySelectorAll('span');
@@ -2809,14 +2623,17 @@
     const fieldOffsetClass = classList[0];
     assert(fieldOffsetClass.startsWith('field-offset-'));
 
-    function configureMatchingItem(className, callback, root) {
+    function configureMatchingItem(
+        className: string, callback: (e: CrTreeItemElement) => void,
+        root: CrTreeElement|CrTreeItemElement) {
       if (root.tagName === 'CR-TREE-ITEM' &&
           root.classList.contains(className)) {
-        callback(root);
+        callback(root as CrTreeItemElement);
         return true;
       }
       for (const item of root.items) {
-        if (configureMatchingItem(className, callback, item)) {
+        if (configureMatchingItem(
+                className, callback, item as CrTreeItemElement)) {
           return true;
         }
       }
@@ -2844,22 +2661,25 @@
   });
 }
 
+type Field = {
+  size: number,
+  label: string,
+  formatter: (data: Uint8Array, offset: number) => string,
+  extraTreeItemFormatter?: (data: Uint8Array, offset: number,
+                            item: CrTreeItemElement, label: string) => void,
+};
+
 /**
  * Renders a tree view to display the raw data in readable text.
- * @param {!CrTreeElement|!CrTreeItemElement} root
- * @param {!HTMLElement} rawDataByteElement
- * @param {!Array<Object>} fields
- * @param {!Uint8Array} rawData
- * @param {number} offset The start offset of the descriptor structure that
+ * @param offset The start offset of the descriptor structure that
  *     want to be rendered.
- * @param {!HTMLElement} rootElement
- * @param {...string} parentClassNames
- * @return {number} The end offset of descriptor structure that want to be
+ * @return The end offset of descriptor structure that want to be
  *     rendered.
  */
 function renderRawDataTree(
-    root, rawDataByteElement, fields, rawData, offset, rootElement,
-    ...parentClassNames) {
+    root: CrTreeElement|CrTreeItemElement, rawDataByteElement: HTMLElement,
+    fields: Field[], rawData: Uint8Array, offset: number,
+    rootElement: HTMLElement, ...parentClassNames: string[]): number {
   const rawDataByteElements = rawDataByteElement.querySelectorAll('span');
 
   for (const field of fields) {
@@ -2870,9 +2690,9 @@
           `${field.label}${field.formatter(rawData, offset)}`, className);
 
       for (let i = 0; i < field.size; i++) {
-        rawDataByteElements[offset + i].classList.add(className);
+        rawDataByteElements[offset + i]!.classList.add(className);
         for (const parentClassName of parentClassNames) {
-          rawDataByteElements[offset + i].classList.add(parentClassName);
+          rawDataByteElements[offset + i]!.classList.add(parentClassName);
         }
       }
     } catch (e) {
@@ -2887,8 +2707,9 @@
         field.extraTreeItemFormatter(rawData, offset, item, field.label);
       }
     } catch (e) {
+      const message = (e as Error).message;
       showError(
-          `Error at rendering field at index ${offset}: ${e.message}`,
+          `Error at rendering field at index ${offset}: ${message}`,
           rootElement);
     }
     offset += field.size;
@@ -2898,38 +2719,40 @@
 
 /**
  * Renders an element to display the raw data in hex, byte by byte.
- * @param {!HTMLElement} rawDataByteElement
- * @param {!Uint8Array} rawData
  */
-function renderRawDataBytes(rawDataByteElement, rawData) {
-  const rawDataByteContainerTemplate = queryRequiredElement(
-      '#raw-data-byte-container-template',
-      /** @type {!DocumentFragment} */ (rawDataByteElement.getRootNode()));
-  const rawDataByteContainerClone =
+function renderRawDataBytes(
+    rawDataByteElement: HTMLElement, rawData: Uint8Array) {
+  const rawDataByteContainerTemplate =
+      (rawDataByteElement.getRootNode() as HTMLElement)
+          .querySelector<HTMLTemplateElement>(
+              '#raw-data-byte-container-template');
+  assert(rawDataByteContainerTemplate);
+  const rawDataByteContainerClone: DocumentFragment =
       document.importNode(rawDataByteContainerTemplate.content, true);
   const rawDataByteContainerElement =
       rawDataByteContainerClone.querySelector('div');
+  assert(rawDataByteContainerElement);
 
-  const rawDataByteTemplate = queryRequiredElement(
-      '#raw-data-byte-template',
-      /** @type {!DocumentFragment} */ (rawDataByteElement.getRootNode()));
+  const rawDataByteTemplate =
+      (rawDataByteElement.getRootNode() as HTMLElement)
+          .querySelector<HTMLTemplateElement>('#raw-data-byte-template');
+  assert(rawDataByteTemplate);
   for (const value of rawData) {
-    const rawDataByteClone =
+    const rawDataByteClone: DocumentFragment =
         document.importNode(rawDataByteTemplate.content, true);
-    const rawDataByteElement = rawDataByteClone.querySelector('span');
-    rawDataByteElement.textContent = toHex(value, 2);
-    rawDataByteContainerElement.appendChild(rawDataByteElement);
+    const rawDataByteSpan = rawDataByteClone.querySelector('span');
+    assert(rawDataByteSpan);
+    rawDataByteSpan.textContent = toHex(value, 2);
+    rawDataByteContainerElement.appendChild(rawDataByteSpan);
   }
   rawDataByteElement.appendChild(rawDataByteContainerElement);
 }
 
 /**
  * Checks if the status of a control transfer indicates success.
- * @param {number} status
- * @param {string} defaultMessage
- * @param {!HTMLElement} rootElement
  */
-function checkTransferSuccess(status, defaultMessage, rootElement) {
+function checkTransferSuccess(
+    status: number, defaultMessage: string, rootElement: HTMLElement) {
   let failReason = '';
   switch (status) {
     case UsbTransferStatus.COMPLETED:
@@ -2967,21 +2790,16 @@
 /**
  * Converts a number to a hexadecimal string padded with zeros to the given
  * number of digits.
- * @param {number} number
- * @param {number} numOfDigits
- * @return {string}
  */
-function toHex(number, numOfDigits) {
+function toHex(number: number, numOfDigits: number): string {
   return number.toString(16).padStart(numOfDigits, '0').toUpperCase();
 }
 
 /**
  * Parses UTF-16 array to string.
- * @param {!Uint8Array} arr
- * @param {boolean=} isLittleEndian
- * @return {string}
  */
-function decodeUtf16Array(arr, isLittleEndian = false) {
+function decodeUtf16Array(
+    arr: Uint8Array, isLittleEndian: boolean = false): string {
   let str = '';
   const data = new DataView(arr.buffer);
   for (let i = 0; i < arr.length; i += 2) {
@@ -2992,104 +2810,76 @@
 
 /**
  * Parses UTF-8 array to string.
- * @param {!Uint8Array} arr
- * @return {string}
  */
-function decodeUtf8Array(arr) {
+function decodeUtf8Array(arr: Uint8Array): string {
   return String.fromCodePoint(...arr);
 }
 
 /**
  * Parses one byte to decimal number string.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatByte(rawData, offset) {
-  return rawData[offset].toString();
+function formatByte(rawData: Uint8Array, offset: number): string {
+  return rawData[offset]!.toString();
 }
 
 /**
  * Parses two bytes to decimal number.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {number}
  */
-function parseShort(rawData, offset) {
+function parseShort(rawData: Uint8Array, offset: number): number {
   const data = new DataView(rawData.buffer);
   return data.getUint16(offset, true);
 }
 
 /**
  * Parses two bytes to decimal number string.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
+ :
  */
-function formatShort(rawData, offset) {
+function formatShort(rawData: Uint8Array, offset: number): string {
   return parseShort(rawData, offset).toString();
 }
 
 /**
  * Parses two bytes to decimal number string.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatLetter(rawData, offset) {
+function formatLetter(rawData: Uint8Array, offset: number): string {
   const num = parseShort(rawData, offset);
   return String.fromCodePoint(num);
 }
 
 /**
  * Parses two bytes to a hex string.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatTwoBytesToHex(rawData, offset) {
+function formatTwoBytesToHex(rawData: Uint8Array, offset: number): string {
   const num = parseShort(rawData, offset);
   return `0x${toHex(num, 4)}`;
 }
 
 /**
  * Parses two bytes to USB version format.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatUsbVersion(rawData, offset) {
-  return `${rawData[offset + 1]}.${rawData[offset] >> 4}.${
-      rawData[offset] & 0x0F}`;
+function formatUsbVersion(rawData: Uint8Array, offset: number): string {
+  return `${rawData[offset + 1]}.${rawData[offset]! >> 4}.${
+      rawData[offset]! & 0x0F}`;
 }
 
 /**
  * Parses one byte to a bitmap.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatBitmap(rawData, offset) {
-  return rawData[offset].toString(2).padStart(8, '0');
+function formatBitmap(rawData: Uint8Array, offset: number): string {
+  return rawData[offset]!.toString(2).padStart(8, '0');
 }
 
 /**
  * Parses descriptor type to a hex string.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatDescriptorType(rawData, offset) {
-  return `0x${toHex(rawData[offset], 2)}`;
+function formatDescriptorType(rawData: Uint8Array, offset: number): string {
+  return `0x${toHex(rawData[offset]!, 2)}`;
 }
 
 /**
  * Parses UUID field.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatUuid(rawData, offset) {
+function formatUuid(rawData: Uint8Array, offset: number): string {
   // UUID is 16 bytes (Section 9.6.2.4 of Universal Serial Bus 3.1
   // Specification).
   // Additional reference: IETF RFC 4122. https://tools.ietf.org/html/rfc4122
@@ -3117,11 +2907,8 @@
 
 /**
  * Parses Compatible ID String field.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatCompatibleIdString(rawData, offset) {
+function formatCompatibleIdString(rawData: Uint8Array, offset: number): string {
   // Compatible ID String is 8 bytes, which is defined by Microsoft OS 2.0
   // Descriptors Specification (July, 2018).
   return decodeUtf8Array(rawData.slice(offset, offset + 8));
@@ -3129,11 +2916,8 @@
 
 /**
  * Parses Windows Version field.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatWindowsVersion(rawData, offset) {
+function formatWindowsVersion(rawData: Uint8Array, offset: number): string {
   const data = new DataView(rawData.buffer);
   const windowsVersion = data.getUint32(offset, true);
   switch (windowsVersion) {
@@ -3146,11 +2930,9 @@
 
 /**
  * Parses Feature Registry Property Data Type.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatFeatureRegistryPropertyDataType(rawData, offset) {
+function formatFeatureRegistryPropertyDataType(
+    rawData: Uint8Array, offset: number): string {
   const data = new DataView(rawData.buffer);
   const propertyDataType = data.getUint16(offset, true);
   switch (propertyDataType) {
@@ -3177,30 +2959,22 @@
 
 /**
  * Returns empty string for a field that can't or doesn't need to be parsed.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatUnknown(rawData, offset) {
+function formatUnknown(_rawData: Uint8Array, _offset: number): string {
   return '';
 }
 
 /**
  * Returns a class code string with a description.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @return {string}
  */
-function formatClassCode(rawData, offset) {
-  return renderClassCodeWithDescription(rawData[offset]);
+function formatClassCode(rawData: Uint8Array, offset: number): string {
+  return renderClassCodeWithDescription(rawData[offset]!);
 }
 
 /**
  * Returns a class code string with a description.
- * @param {number} classCode
- * @return {string}
  */
-export function renderClassCodeWithDescription(classCode) {
+export function renderClassCodeWithDescription(classCode: number): string {
   const blockedByWebUsb = '(blocked by WebUSB)';
   // USB Class Codes are defined by the USB-IF:
   // https://www.usb.org/defined-class-codes
@@ -3255,10 +3029,8 @@
 
 /**
  * Parses language code to readable language name.
- * @param {number} languageCode
- * @return {string}
  */
-function parseLanguageCode(languageCode) {
+function parseLanguageCode(languageCode: number): string {
   switch (languageCode) {
     case LANGUAGE_CODE_EN_US:
       return 'en-US';
@@ -3269,11 +3041,9 @@
 
 /**
  * Checks if two UUIDs are same.
- * @param {!Uint8Array} rawData
- * @param {number} offset The offset of current field.
- * @param {!Array<number>} uuidArr
  */
-function isSameUuid(rawData, offset, uuidArr) {
+function isSameUuid(
+    rawData: Uint8Array, offset: number, uuidArr: number[]): boolean {
   // Validate the Platform Capability Descriptor
   if (offset + 20 > rawData.length) {
     return false;
@@ -3287,6 +3057,3 @@
   }
   return true;
 }
-
-window.deviceDescriptorCompleteFn =
-    window.deviceDescriptorCompleteFn || function() {};
diff --git a/chrome/browser/resources/usb_internals/devices_page.js b/chrome/browser/resources/usb_internals/devices_page.js
index 8b6acae4..5a83aad 100644
--- a/chrome/browser/resources/usb_internals/devices_page.js
+++ b/chrome/browser/resources/usb_internals/devices_page.js
@@ -14,10 +14,36 @@
 import {queryRequiredElement} from 'chrome://resources/js/util.m.js';
 import {String16} from 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-webui.js';
 
-import {CrTreeElement, CrTreeItemElement, DescriptorPanel, renderClassCodeWithDescription} from './descriptor_panel.js';
+import {DescriptorPanel, renderClassCodeWithDescription} from './descriptor_panel.js';
 import {UsbAlternateInterfaceInfo, UsbConfigurationInfo, UsbDeviceInfo, UsbDeviceRemote, UsbEndpointInfo, UsbInterfaceInfo, UsbTransferDirection, UsbTransferType} from './usb_device.mojom-webui.js';
 import {UsbDeviceManagerRemote} from './usb_manager.mojom-webui.js';
 
+// TODO (rbpotter): Remove these temporary definitions after migrating to TS.
+/**
+ * @typedef {{
+ *   expanded: boolean,
+ *   add: function(CrTreeItemElement): void,
+ *   labelElement: HTMLElement,
+ *   rowElement: HTMLElement,
+ *   forceHoverStyle: function(boolean): void,
+ * }}
+ */
+export let CrTreeItemElement;
+
+/**
+ * @typedef {{
+ *   add: function(CrTreeItemElement): void,
+ *   detail: {payload: Object, children: Object},
+ *   removeTreeItem: function(CrTreeItemElement): void,
+ *   expanded: boolean,
+ *   items: Array<CrTreeItemElement>,
+ *   selectedItem: CrTreeItemElement,
+ * }}
+ */
+export let CrTreeElement;
+
+
+
 /**
  * Page that contains a tab header and a tab panel displaying devices table.
  */
diff --git a/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc b/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc
index 33c9e50..30d1ab5 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc
@@ -154,14 +154,8 @@
   }
 }
 
-#if BUILDFLAG(IS_MAC)
-// TODO(crbug.com/): Re-enable this test
-#define MAYBE_TfLiteClassification DISABLED_TfLiteClassification
-#else
-#define MAYBE_TfLiteClassification TfLiteClassification
-#endif
 IN_PROC_BROWSER_TEST_F(ClientSideDetectionServiceBrowserTest,
-                       MAYBE_TfLiteClassification) {
+                       TfLiteClassification) {
   GURL url(embedded_test_server()->GetURL("/empty.html"));
   ASSERT_TRUE(content::NavigateToURL(web_contents(), url));
 
diff --git a/chrome/browser/safe_browsing/download_protection/file_analyzer.cc b/chrome/browser/safe_browsing/download_protection/file_analyzer.cc
index a3944937..380eda5 100644
--- a/chrome/browser/safe_browsing/download_protection/file_analyzer.cc
+++ b/chrome/browser/safe_browsing/download_protection/file_analyzer.cc
@@ -85,6 +85,7 @@
   target_path_ = target_path;
   tmp_path_ = tmp_path;
   callback_ = std::move(callback);
+  start_time_ = base::Time::Now();
 
   results_.type = download_type_util::GetDownloadType(target_path_);
 
@@ -135,6 +136,7 @@
 }
 
 void FileAnalyzer::OnFileAnalysisFinished(FileAnalyzer::Results results) {
+  LogAnalysisDurationWithAndWithoutSuffix("Executable");
   results.type = download_type_util::GetDownloadType(target_path_);
   std::move(callback_).Run(results);
 }
@@ -156,6 +158,7 @@
     const ArchiveAnalyzerResults& archive_results) {
   base::UmaHistogramEnumeration("SBClientDownload.ZipArchiveAnalysisResult",
                                 archive_results.analysis_result);
+  LogAnalysisDurationWithAndWithoutSuffix("Zip");
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // Even if !results.success, some of the zip may have been parsed.
@@ -204,6 +207,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   base::UmaHistogramEnumeration("SBClientDownload.RarArchiveAnalysisResult",
                                 archive_results.analysis_result);
+  LogAnalysisDurationWithAndWithoutSuffix("Rar");
 
   results_.archive_is_valid =
       (archive_results.success ? ArchiveValid::VALID : ArchiveValid::INVALID);
@@ -262,6 +266,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   base::UmaHistogramEnumeration("SBClientDownload.DmgArchiveAnalysisResult",
                                 archive_results.analysis_result);
+  LogAnalysisDurationWithAndWithoutSuffix("Dmg");
 
   if (archive_results.signature_blob.size() > 0) {
     results_.disk_image_signature =
@@ -309,11 +314,9 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // Log metrics for Document Analysis.
-  UMA_HISTOGRAM_BOOLEAN("SBClientDownload.DocumentAnalysisSuccess",
-                        document_results.success);
-  UMA_HISTOGRAM_MEDIUM_TIMES(
-      "SBClientDownload.ExtractDocumentFeaturesTimeMedium",
-      base::TimeTicks::Now() - document_analysis_start_time_);
+  base::UmaHistogramBoolean("SBClientDownload.DocumentAnalysisSuccess",
+                            document_results.success);
+  LogAnalysisDurationWithAndWithoutSuffix("Document");
 
   ClientDownloadRequest::DocumentSummary document_summary;
   ClientDownloadRequest::DocumentInfo* document_info =
@@ -335,4 +338,14 @@
   std::move(callback_).Run(std::move(results_));
 }
 #endif
+
+void FileAnalyzer::LogAnalysisDurationWithAndWithoutSuffix(
+    const std::string& suffix) {
+  base::UmaHistogramMediumTimes("SBClientDownload.FileAnalysisDuration",
+                                base::Time::Now() - start_time_);
+  base::UmaHistogramMediumTimes(
+      "SBClientDownload.FileAnalysisDuration." + suffix,
+      base::Time::Now() - start_time_);
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/download_protection/file_analyzer.h b/chrome/browser/safe_browsing/download_protection/file_analyzer.h
index 15caa54..9611097 100644
--- a/chrome/browser/safe_browsing/download_protection/file_analyzer.h
+++ b/chrome/browser/safe_browsing/download_protection/file_analyzer.h
@@ -118,10 +118,13 @@
       const DocumentAnalyzerResults& document_results);
 #endif
 
+  void LogAnalysisDurationWithAndWithoutSuffix(const std::string& suffix);
+
   base::FilePath target_path_;
   base::FilePath tmp_path_;
   scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_;
   base::OnceCallback<void(Results)> callback_;
+  base::Time start_time_;
   Results results_;
 
   scoped_refptr<SandboxedZipAnalyzer> zip_analyzer_;
diff --git a/chrome/browser/safety_check/android/BUILD.gn b/chrome/browser/safety_check/android/BUILD.gn
index 4270c58..e9fab797 100644
--- a/chrome/browser/safety_check/android/BUILD.gn
+++ b/chrome/browser/safety_check/android/BUILD.gn
@@ -93,9 +93,7 @@
   ]
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java" ]
   deps = [
diff --git a/chrome/browser/signin/services/android/BUILD.gn b/chrome/browser/signin/services/android/BUILD.gn
index d0d550a..c7168470 100644
--- a/chrome/browser/signin/services/android/BUILD.gn
+++ b/chrome/browser/signin/services/android/BUILD.gn
@@ -81,9 +81,7 @@
   ]
 }
 
-android_library("junit") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "junit/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheUnitTest.java",
diff --git a/chrome/browser/tab/BUILD.gn b/chrome/browser/tab/BUILD.gn
index 7209e7d..0766f17f 100644
--- a/chrome/browser/tab/BUILD.gn
+++ b/chrome/browser/tab/BUILD.gn
@@ -145,8 +145,7 @@
   sources = [ "$root_dir/critical_persisted_tab_data.fbs" ]
 }
 
-android_library("junit") {
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/chrome/browser/tab/CurrentTabObserverTest.java",
diff --git a/chrome/browser/tab_group/BUILD.gn b/chrome/browser/tab_group/BUILD.gn
index 7bada13..06c28a0 100644
--- a/chrome/browser/tab_group/BUILD.gn
+++ b/chrome/browser/tab_group/BUILD.gn
@@ -21,9 +21,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   sources = [
diff --git a/chrome/browser/tabmodel/BUILD.gn b/chrome/browser/tabmodel/BUILD.gn
index db6be0ff..60cfdf7 100644
--- a/chrome/browser/tabmodel/BUILD.gn
+++ b/chrome/browser/tabmodel/BUILD.gn
@@ -66,9 +66,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   sources = [ "android/java/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java" ]
diff --git a/chrome/browser/tabpersistence/BUILD.gn b/chrome/browser/tabpersistence/BUILD.gn
index 70a9f51f..f6d3d66 100644
--- a/chrome/browser/tabpersistence/BUILD.gn
+++ b/chrome/browser/tabpersistence/BUILD.gn
@@ -20,9 +20,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "android/java/src/org/chromium/chrome/browser/tabpersistence/TabStateFileManagerUnitTest.java" ]
   deps = [
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 9485c8b..38060d0 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -413,6 +413,7 @@
     "//chrome/browser/breadcrumbs",
     "//chrome/browser/commerce/shopping_list",
     "//chrome/browser/devtools",
+    "//chrome/browser/favicon",
     "//chrome/browser/image_decoder",
     "//chrome/browser/media:mojo_bindings",
     "//chrome/browser/media/router:media_router_feature",
@@ -678,6 +679,7 @@
   allow_circular_includes_from = [
     # TODO(crbug.com/1158905): Remove this circular dependency.
     "//chrome/browser/devtools",
+    "//chrome/browser/favicon",
     "//chrome/browser/safe_browsing",
     "//chrome/browser/ui/webui/bluetooth_internals",
     "//chrome/browser/profiling_host",
@@ -3019,6 +3021,7 @@
       "//ash/components/disks",
       "//ash/components/drivefs",
       "//ash/components/drivefs/mojom:mojom",
+      "//ash/components/fwupd",
       "//ash/components/login/auth",
       "//ash/components/login/session",
       "//ash/components/multidevice",
diff --git a/chrome/browser/ui/android/appmenu/internal/BUILD.gn b/chrome/browser/ui/android/appmenu/internal/BUILD.gn
index 2f7953c..45dfb35 100644
--- a/chrome/browser/ui/android/appmenu/internal/BUILD.gn
+++ b/chrome/browser/ui/android/appmenu/internal/BUILD.gn
@@ -114,9 +114,7 @@
   deps = [ ":java_resources" ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuPopupPositionTest.java" ]
   deps = [
diff --git a/chrome/browser/ui/android/autofill/internal/BUILD.gn b/chrome/browser/ui/android/autofill/internal/BUILD.gn
index 8223699..09d374f 100644
--- a/chrome/browser/ui/android/autofill/internal/BUILD.gn
+++ b/chrome/browser/ui/android/autofill/internal/BUILD.gn
@@ -53,9 +53,7 @@
   ]
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/chrome/browser/ui/autofill/AuthenticatorSelectionDialogBridgeTest.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..b360025 100644
--- a/chrome/browser/ui/android/default_browser_promo/BUILD.gn
+++ b/chrome/browser/ui/android/default_browser_promo/BUILD.gn
@@ -22,9 +22,7 @@
   resources_package = "org.chromium.chrome.browser.ui.default_browser_promo"
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "java/src/org/chromium/chrome/browser/ui/default_browser_promo/DefaultBrowserPromoUtilsTest.java" ]
   deps = [
diff --git a/chrome/browser/ui/android/layouts/BUILD.gn b/chrome/browser/ui/android/layouts/BUILD.gn
index 76ea86b..9d0e4b7c 100644
--- a/chrome/browser/ui/android/layouts/BUILD.gn
+++ b/chrome/browser/ui/android/layouts/BUILD.gn
@@ -52,9 +52,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   sources = [
diff --git a/chrome/browser/ui/android/logo/BUILD.gn b/chrome/browser/ui/android/logo/BUILD.gn
index fda140b..9365bca 100644
--- a/chrome/browser/ui/android/logo/BUILD.gn
+++ b/chrome/browser/ui/android/logo/BUILD.gn
@@ -74,9 +74,7 @@
   ]
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   sources = [
diff --git a/chrome/browser/ui/android/multiwindow/BUILD.gn b/chrome/browser/ui/android/multiwindow/BUILD.gn
index 04f3a06..52bbfe15 100644
--- a/chrome/browser/ui/android/multiwindow/BUILD.gn
+++ b/chrome/browser/ui/android/multiwindow/BUILD.gn
@@ -67,11 +67,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
-  testonly = true
-
+robolectric_library("junit") {
   sources = [
     "java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceStateUnitTest.java",
     "java/src/org/chromium/chrome/browser/multiwindow/UiUtilsUnitTest.java",
@@ -85,7 +81,6 @@
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/util:java",
     "//components/favicon/android:java",
-    "//third_party/android_deps:robolectric_all_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/androidx:androidx_test_core_java",
     "//third_party/androidx:androidx_test_runner_java",
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceStateUnitTest.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceStateUnitTest.java
index a96e151..864699a 100644
--- a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceStateUnitTest.java
+++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceStateUnitTest.java
@@ -66,6 +66,7 @@
             ApplicationStatus.onStateChangeForTesting(this, ActivityState.STOPPED);
         }
 
+        @Override
         public void destroy() {
             AppTask appTask = null;
             for (AppTask task : sTasks.keySet()) {
@@ -125,7 +126,7 @@
         RecentTaskInfo taskInfo = new RecentTaskInfo();
         taskInfo.id = taskId;
         taskInfo.baseActivity = new ComponentName(
-                activity.getClass().getPackageName(), activity.getClass().getName());
+                activity.getClass().getPackage().getName(), activity.getClass().getName());
         sTasks.put(new AppTask(null), taskInfo);
         ApplicationStatus.onStateChangeForTesting(activity, ActivityState.CREATED);
         ApplicationStatus.onStateChangeForTesting(activity, ActivityState.RESUMED);
diff --git a/chrome/browser/ui/android/native_page/BUILD.gn b/chrome/browser/ui/android/native_page/BUILD.gn
index f553099..dd53c11b 100644
--- a/chrome/browser/ui/android/native_page/BUILD.gn
+++ b/chrome/browser/ui/android/native_page/BUILD.gn
@@ -21,9 +21,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   sources = [
diff --git a/chrome/browser/ui/android/night_mode/BUILD.gn b/chrome/browser/ui/android/night_mode/BUILD.gn
index 895c78c..a9ed3097 100644
--- a/chrome/browser/ui/android/night_mode/BUILD.gn
+++ b/chrome/browser/ui/android/night_mode/BUILD.gn
@@ -104,9 +104,7 @@
   resources_package = "org.chromium.chrome.browser.night_mode"
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/chrome/browser/night_mode/AutoDarkFeedbackSourceUnitTest.java",
diff --git a/chrome/browser/ui/android/omnibox/BUILD.gn b/chrome/browser/ui/android/omnibox/BUILD.gn
index 2878bbe0..d3254c8b 100644
--- a/chrome/browser/ui/android/omnibox/BUILD.gn
+++ b/chrome/browser/ui/android/omnibox/BUILD.gn
@@ -347,9 +347,7 @@
   sources = [ "$proto_path/partner_location_descriptor.proto" ]
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   sources = [
diff --git a/chrome/browser/ui/android/signin/BUILD.gn b/chrome/browser/ui/android/signin/BUILD.gn
index 2a69434a..3545aa5 100644
--- a/chrome/browser/ui/android/signin/BUILD.gn
+++ b/chrome/browser/ui/android/signin/BUILD.gn
@@ -135,8 +135,7 @@
   ]
 }
 
-android_library("junit") {
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "junit/src/org/chromium/chrome/browser/ui/signin/ConfirmSyncDataStateMachineTest.java",
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index dffccfde..61087103 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -807,16 +807,8 @@
         Touch to Search
       </message>
       <message name="IDS_CONTEXTUAL_SEARCH_DESCRIPTION" desc="Description for Contextual Search preference">
-        Learn about topics on websites without leaving the page. Touch to Search sends a word and its surrounding context to Google Search, returning definitions, pictures, search results, and other details.
-
-Touch &amp; hold any word to search. To refine your search, select more or fewer words. To edit your search, open the panel, tap the icon to open in a new tab, and make your changes in the search box.
-      </message>
-      <message name="IDS_CONTEXTUAL_SEARCH_DESCRIPTION_REVISED" desc="Description for Contextual Search preference">
         Learn about topics on websites without leaving the page. Select one or more words on the page to search for them.
       </message>
-      <message name="IDS_CONTEXTUAL_SEARCH_SHORT_DESCRIPTION" desc="A promo message shown to users with Touch to Search to explain the new behavior and provide an option to opt in or out">
-        Touch to Search sends the selected word and the current page as context to Google Search. You can turn it off in <ph name="BEGIN_LINK">&lt;link&gt;</ph>Settings<ph name="END_LINK">&lt;/link&gt;</ph>.
-      </message>
       <message name="IDS_CONTEXTUAL_SEARCH_PROMO_TITLE" desc="The title of the promo message for the contextual search.">
         Include surrounding text in Google searches?
       </message>
@@ -826,9 +818,6 @@
       <message name="IDS_CONTEXTUAL_SEARCH_INCLUDE_BUTTON" desc="A button to confirm and dismiss opt in promo">
         Include
       </message>
-      <message name="IDS_CONTEXTUAL_SEARCH_ALLOW_BUTTON" desc="A button to confirm and dismiss opt out promo">
-        Allow
-      </message>
       <message name="IDS_CONTEXTUAL_SEARCH_NO_THANKS_BUTTON" desc="A button to confirm and dismiss opt out promo">
         No thanks
       </message>
@@ -5657,6 +5646,11 @@
       <message name="IDS_PASSWORD_EDIT_DIALOG_UNSYNCED_FOOTER" desc="Footer for a dialog which allows users to see and edit passwords while saving/updating a new credential. Displayed for users who are not syncing passwords.">
         Passwords are saved to Password Manager on this device
       </message>
+
+      <!-- Price tracking strings -->
+      <message name="IDS_PRICE_DROP_SPOTTED_IPH" desc="This text appears in the IPH when a user opens a new tab page and an item in any of their open tabs has a price drop.">
+        Price drop spotted
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_DESCRIPTION.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_DESCRIPTION.png.sha1
index fdfad73..37f4f15d 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_DESCRIPTION.png.sha1
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_DESCRIPTION.png.sha1
@@ -1 +1 @@
-7cf625922cfcbfe489fb4bacdaf947b0a3f9f2b7
\ No newline at end of file
+6802403d5c13b0b9583d5ca660caa390d7928fce
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_DESCRIPTION_REVISED.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_DESCRIPTION_REVISED.png.sha1
deleted file mode 100644
index 088ccce..0000000
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_DESCRIPTION_REVISED.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7a9ff6cf847d62c9454fd93f371d35934d9271db
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_SHORT_DESCRIPTION.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_SHORT_DESCRIPTION.png.sha1
deleted file mode 100644
index d749d4fbb..0000000
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTUAL_SEARCH_SHORT_DESCRIPTION.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-66ebbb0629718c5e279cd508afdb3f7d15590569
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRICE_DROP_SPOTTED_IPH.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRICE_DROP_SPOTTED_IPH.png.sha1
new file mode 100644
index 0000000..3b7003c0
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRICE_DROP_SPOTTED_IPH.png.sha1
@@ -0,0 +1 @@
+47eedb698c856fe9ea0f17a4642f2cf17f522138
\ 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 727820db..5b37441 100644
--- a/chrome/browser/ui/android/toolbar/BUILD.gn
+++ b/chrome/browser/ui/android/toolbar/BUILD.gn
@@ -269,9 +269,7 @@
   ]
 }
 
-android_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   sources = [
diff --git a/chrome/browser/ui/android/webid/internal/BUILD.gn b/chrome/browser/ui/android/webid/internal/BUILD.gn
index 7ab2c3ea..3e60f4d 100644
--- a/chrome/browser/ui/android/webid/internal/BUILD.gn
+++ b/chrome/browser/ui/android/webid/internal/BUILD.gn
@@ -65,10 +65,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
-
+robolectric_library("junit") {
   testonly = true
 
   sources = [ "java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java" ]
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBridge.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBridge.java
index e2118ba..5a1a7f3 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBridge.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBridge.java
@@ -26,6 +26,12 @@
  * forwards native calls to it.
  */
 class AccountSelectionBridge implements AccountSelectionComponent.Delegate {
+    /**
+     * The size of the maskable icon's safe zone as a fraction of the icon's edge size as defined
+     * in https://www.w3.org/TR/appmanifest/
+     */
+    public static final float MASKABLE_ICON_SAFE_ZONE_DIAMETER_RATIO = 0.8f;
+
     private long mNativeView;
     private final AccountSelectionComponent mAccountSelectionComponent;
 
@@ -49,7 +55,8 @@
     @CalledByNative
     static int getBrandIconIdealSize() {
         Resources resources = ContextUtils.getApplicationContext().getResources();
-        return Math.round(resources.getDimension(R.dimen.account_selection_sheet_icon_size));
+        return Math.round(resources.getDimension(R.dimen.account_selection_sheet_icon_size)
+                / MASKABLE_ICON_SAFE_ZONE_DIAMETER_RATIO);
     }
 
     @CalledByNative
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java
index 1b84977..5939dfeb 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java
@@ -61,12 +61,6 @@
     private static final String TAG = "AccountSelectionView";
 
     /**
-     * The size of the maskable icon's safe zone as a fraction of the icon's edge size as defined
-     * in https://www.w3.org/TR/appmanifest/
-     */
-    private static final float MASKABLE_ICON_SAFE_ZONE_DIAMETER_RATIO = 0.8f;
-
-    /**
      * Returns bitmap with the maskable bitmap's safe zone as defined in
      * https://www.w3.org/TR/appmanifest/ cropped in a circle.
      * @param resources the Resources used to set initial target density.
@@ -77,10 +71,10 @@
      */
     public static Drawable createBitmapWithMaskableIconSafeZone(
             Resources resources, Bitmap bitmap, int outBitmapSize) {
-        int cropWidth =
-                (int) Math.floor(bitmap.getWidth() * MASKABLE_ICON_SAFE_ZONE_DIAMETER_RATIO);
-        int cropHeight =
-                (int) Math.floor(bitmap.getHeight() * MASKABLE_ICON_SAFE_ZONE_DIAMETER_RATIO);
+        int cropWidth = (int) Math.floor(
+                bitmap.getWidth() * AccountSelectionBridge.MASKABLE_ICON_SAFE_ZONE_DIAMETER_RATIO);
+        int cropHeight = (int) Math.floor(
+                bitmap.getHeight() * AccountSelectionBridge.MASKABLE_ICON_SAFE_ZONE_DIAMETER_RATIO);
         int cropX = (int) Math.floor((bitmap.getWidth() - cropWidth) / 2.0f);
         int cropY = (int) Math.floor((bitmap.getHeight() - cropHeight) / 2.0f);
 
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc b/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc
index bb0d1d2..20c9d02 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/ash/shelf/arc_app_shelf_id.h"
-#include "chrome/common/chrome_features.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/app_update.h"
@@ -138,27 +137,15 @@
       apps::AppServiceProxyFactory::GetForProfile(profile());
 
   auto icon_type = apps::IconType::kStandard;
-  auto mojom_icon_type = apps::mojom::IconType::kStandard;
 
   // When Crostini generates shelf id as the app_id, which couldn't match to an
   // app, the default penguin icon should be loaded.
   if (crostini::IsUnmatchedCrostiniShelfAppId(app_id)) {
-    if (base::FeatureList::IsEnabled(
-            features::kAppServiceLoadIconWithoutMojom)) {
-      apps::IconKey icon_key;
-      proxy->LoadIconFromIconKey(
-          apps::AppType::kCrostini, app_id, icon_key, icon_type,
-          icon_size_in_dip(), allow_placeholder_icon,
-          base::BindOnce(&AppServiceAppIconLoader::OnLoadIcon,
-                         weak_ptr_factory_.GetWeakPtr(), app_id));
-    } else {
-      apps::mojom::IconKeyPtr icon_key = apps::mojom::IconKey::New();
-      proxy->LoadIconFromIconKey(
-          apps::mojom::AppType::kCrostini, app_id, std::move(icon_key),
-          mojom_icon_type, icon_size_in_dip(), allow_placeholder_icon,
-          base::BindOnce(&AppServiceAppIconLoader::OnLoadMojomIcon,
-                         weak_ptr_factory_.GetWeakPtr(), app_id));
-    }
+    proxy->LoadIconFromIconKey(
+        apps::AppType::kCrostini, app_id, apps::IconKey(), icon_type,
+        icon_size_in_dip(), allow_placeholder_icon,
+        base::BindOnce(&AppServiceAppIconLoader::OnLoadIcon,
+                       weak_ptr_factory_.GetWeakPtr(), app_id));
     return;
   }
 
@@ -167,17 +154,10 @@
     return;
   }
 
-  if (base::FeatureList::IsEnabled(features::kAppServiceLoadIconWithoutMojom)) {
-    proxy->LoadIcon(app_type, app_id, icon_type, icon_size_in_dip(),
-                    allow_placeholder_icon,
-                    base::BindOnce(&AppServiceAppIconLoader::OnLoadIcon,
-                                   weak_ptr_factory_.GetWeakPtr(), app_id));
-  } else {
-    proxy->LoadIcon(apps::ConvertAppTypeToMojomAppType(app_type), app_id,
-                    mojom_icon_type, icon_size_in_dip(), allow_placeholder_icon,
-                    base::BindOnce(&AppServiceAppIconLoader::OnLoadMojomIcon,
-                                   weak_ptr_factory_.GetWeakPtr(), app_id));
-  }
+  proxy->LoadIcon(app_type, app_id, icon_type, icon_size_in_dip(),
+                  allow_placeholder_icon,
+                  base::BindOnce(&AppServiceAppIconLoader::OnLoadIcon,
+                                 weak_ptr_factory_.GetWeakPtr(), app_id));
 }
 
 void AppServiceAppIconLoader::OnLoadIcon(const std::string& app_id,
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_item.cc b/chrome/browser/ui/app_list/app_service/app_service_app_item.cc
index e8617c0..4e1d4b2 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_item.cc
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_item.cc
@@ -28,7 +28,6 @@
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
 #include "chrome/browser/ui/app_list/app_service/app_service_context_menu.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
-#include "chrome/common/chrome_features.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/mojom/types.mojom-shared.h"
 
@@ -261,22 +260,12 @@
 }
 
 void AppServiceAppItem::CallLoadIcon(bool allow_placeholder_icon) {
-  if (base::FeatureList::IsEnabled(features::kAppServiceLoadIconWithoutMojom)) {
-    apps::AppServiceProxyFactory::GetForProfile(profile())->LoadIcon(
-        app_type_, id(), apps::IconType::kStandard,
-        ash::SharedAppListConfig::instance().default_grid_icon_dimension(),
-        allow_placeholder_icon,
-        base::BindOnce(&AppServiceAppItem::OnLoadIcon,
-                       weak_ptr_factory_.GetWeakPtr()));
-  } else {
-    apps::AppServiceProxyFactory::GetForProfile(profile())->LoadIcon(
-        apps::ConvertAppTypeToMojomAppType(app_type_), id(),
-        apps::mojom::IconType::kStandard,
-        ash::SharedAppListConfig::instance().default_grid_icon_dimension(),
-        allow_placeholder_icon,
-        apps::MojomIconValueToIconValueCallback(base::BindOnce(
-            &AppServiceAppItem::OnLoadIcon, weak_ptr_factory_.GetWeakPtr())));
-  }
+  apps::AppServiceProxyFactory::GetForProfile(profile())->LoadIcon(
+      app_type_, id(), apps::IconType::kStandard,
+      ash::SharedAppListConfig::instance().default_grid_icon_dimension(),
+      allow_placeholder_icon,
+      base::BindOnce(&AppServiceAppItem::OnLoadIcon,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
 void AppServiceAppItem::OnLoadIcon(apps::IconValuePtr icon_value) {
diff --git a/chrome/browser/ui/app_list/search/app_service_app_result.cc b/chrome/browser/ui/app_list/search/app_service_app_result.cc
index 92f50fe..598a28e 100644
--- a/chrome/browser/ui/app_list/search/app_service_app_result.cc
+++ b/chrome/browser/ui/app_list/search/app_service_app_result.cc
@@ -28,7 +28,6 @@
 #include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
-#include "chrome/common/chrome_features.h"
 #include "components/favicon/core/large_icon_service.h"
 #include "components/services/app_service/public/cpp/app_update.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
@@ -233,21 +232,11 @@
   // If |icon_loader_releaser_| is non-null, assigning to it will signal to
   // |icon_loader_| that the previous icon is no longer being used, as a hint
   // that it could be flushed from any caches.
-  const int dimension = GetIconDimension(chip);
-  if (base::FeatureList::IsEnabled(features::kAppServiceLoadIconWithoutMojom)) {
-    icon_loader_releaser_ = icon_loader_->LoadIcon(
-        app_type_, app_id(), apps::IconType::kStandard, dimension,
-        allow_placeholder_icon,
-        base::BindOnce(&AppServiceAppResult::OnLoadIcon,
-                       weak_ptr_factory_.GetWeakPtr(), chip));
-  } else {
-    icon_loader_releaser_ = icon_loader_->LoadIcon(
-        apps::ConvertAppTypeToMojomAppType(app_type_), app_id(),
-        apps::mojom::IconType::kStandard, dimension, allow_placeholder_icon,
-        apps::MojomIconValueToIconValueCallback(
-            base::BindOnce(&AppServiceAppResult::OnLoadIcon,
-                           weak_ptr_factory_.GetWeakPtr(), chip)));
-  }
+  icon_loader_releaser_ = icon_loader_->LoadIcon(
+      app_type_, app_id(), apps::IconType::kStandard, GetIconDimension(chip),
+      allow_placeholder_icon,
+      base::BindOnce(&AppServiceAppResult::OnLoadIcon,
+                     weak_ptr_factory_.GetWeakPtr(), chip));
 }
 
 void AppServiceAppResult::OnLoadIcon(bool chip, apps::IconValuePtr icon_value) {
diff --git a/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc b/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc
index e1bef894..476e1a7 100644
--- a/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc
+++ b/chrome/browser/ui/ash/shelf/browser_app_shelf_item_controller.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/ash/crosapi/browser_util.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "chrome/browser/ui/ash/shelf/shelf_context_menu.h"
-#include "chrome/common/chrome_features.h"
 #include "components/app_constants/constants.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
@@ -221,22 +220,12 @@
                                              apps::LoadIconCallback callback) {
   const std::string& app_id = shelf_id().app_id;
   auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_);
-  auto app_type = proxy->AppRegistryCache().GetAppType(app_id);
-  if (base::FeatureList::IsEnabled(features::kAppServiceLoadIconWithoutMojom)) {
-    icon_loader_releaser_ = proxy->LoadIcon(
-        app_type, app_id, apps::IconType::kStandard,
-        // matches favicon size
-        /* size_hint_in_dip= */ size_hint_in_dip,
-        /* allow_placeholder_icon= */ false, std::move(callback));
-  } else {
-    icon_loader_releaser_ = proxy->LoadIcon(
-        apps::ConvertAppTypeToMojomAppType(app_type), app_id,
-        apps::mojom::IconType::kStandard,
-        // matches favicon size
-        /* size_hint_in_dip= */ size_hint_in_dip,
-        /* allow_placeholder_icon= */ false,
-        apps::MojomIconValueToIconValueCallback(std::move(callback)));
-  }
+  icon_loader_releaser_ =
+      proxy->LoadIcon(proxy->AppRegistryCache().GetAppType(app_id), app_id,
+                      apps::IconType::kStandard,
+                      // matches favicon size
+                      /* size_hint_in_dip= */ size_hint_in_dip,
+                      /* allow_placeholder_icon= */ false, std::move(callback));
 }
 
 void BrowserAppShelfItemController::OnLoadMediumIcon(
diff --git a/chrome/browser/ui/ash/shelf/standalone_browser_extension_app_shelf_item_controller.cc b/chrome/browser/ui/ash/shelf/standalone_browser_extension_app_shelf_item_controller.cc
index abf6329..e60daf8 100644
--- a/chrome/browser/ui/ash/shelf/standalone_browser_extension_app_shelf_item_controller.cc
+++ b/chrome/browser/ui/ash/shelf/standalone_browser_extension_app_shelf_item_controller.cc
@@ -23,7 +23,6 @@
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h"
 #include "chrome/browser/ui/ash/shelf/standalone_browser_extension_app_context_menu.h"
-#include "chrome/common/chrome_features.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/instance_registry.h"
 #include "ui/base/models/simple_menu_model.h"
@@ -45,27 +44,13 @@
   apps::AppServiceProxy* proxy = apps::AppServiceProxyFactory::GetForProfile(
       ChromeShelfController::instance()->profile());
 
-  constexpr bool kAllowPlaceholderIcon = false;
-  constexpr int32_t kIconSize = 48;
-  if (base::FeatureList::IsEnabled(features::kAppServiceLoadIconWithoutMojom)) {
-    apps::IconKey icon_key;
-    auto icon_type = apps::IconType::kStandard;
-    icon_loader_releaser_ = proxy->LoadIconFromIconKey(
-        apps::AppType::kStandaloneBrowserChromeApp, shelf_id.app_id, icon_key,
-        icon_type, kIconSize, kAllowPlaceholderIcon,
-        base::BindOnce(
-            &StandaloneBrowserExtensionAppShelfItemController::OnLoadIcon,
-            weak_factory_.GetWeakPtr()));
-  } else {
-    apps::mojom::IconKeyPtr icon_key = apps::mojom::IconKey::New();
-    auto icon_type = apps::mojom::IconType::kStandard;
-    icon_loader_releaser_ = proxy->LoadIconFromIconKey(
-        apps::mojom::AppType::kStandaloneBrowserChromeApp, shelf_id.app_id,
-        std::move(icon_key), icon_type, kIconSize, kAllowPlaceholderIcon,
-        apps::MojomIconValueToIconValueCallback(base::BindOnce(
-            &StandaloneBrowserExtensionAppShelfItemController::OnLoadIcon,
-            weak_factory_.GetWeakPtr())));
-  }
+  icon_loader_releaser_ = proxy->LoadIconFromIconKey(
+      apps::AppType::kStandaloneBrowserChromeApp, shelf_id.app_id,
+      apps::IconKey(), apps::IconType::kStandard, /*size_hint_in_dip=*/48,
+      /*allow_placeholder_icon=*/false,
+      base::BindOnce(
+          &StandaloneBrowserExtensionAppShelfItemController::OnLoadIcon,
+          weak_factory_.GetWeakPtr()));
 
   context_menu_ = std::make_unique<StandaloneBrowserExtensionAppContextMenu>(
       shelf_id.app_id,
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 63d64ac..ffd7b80 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -256,6 +256,7 @@
 #endif  // BUILDFLAG(IS_WIN)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/constants/ash_features.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #include "components/session_manager/core/session_manager.h"
 #endif
@@ -1079,10 +1080,14 @@
 }
 
 bool Browser::ShouldDisplayFavicon(content::WebContents* web_contents) const {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   // Suppress for System Apps.
-  if (app_controller_ && app_controller_->system_app()) {
+  if (!base::FeatureList::IsEnabled(
+          chromeos::features::kTerminalMultiProfile) &&
+      app_controller_ && app_controller_->system_app()) {
     return false;
   }
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
   // Otherwise, always display the favicon.
   return true;
diff --git a/chrome/browser/ui/messages/android/BUILD.gn b/chrome/browser/ui/messages/android/BUILD.gn
index 45780e9..77b8284 100644
--- a/chrome/browser/ui/messages/android/BUILD.gn
+++ b/chrome/browser/ui/messages/android/BUILD.gn
@@ -59,10 +59,7 @@
   sources = [ "java/src/org/chromium/chrome/browser/ui/messages/infobar/SimpleConfirmInfoBarBuilder.java" ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
-
+robolectric_library("junit") {
   testonly = true
 
   sources = [ "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollectionUnitTest.java" ]
diff --git a/chrome/browser/ui/tabs/tab_renderer_data.cc b/chrome/browser/ui/tabs/tab_renderer_data.cc
index e6e20ca..3faac39b 100644
--- a/chrome/browser/ui/tabs/tab_renderer_data.cc
+++ b/chrome/browser/ui/tabs/tab_renderer_data.cc
@@ -20,6 +20,11 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/constants/ash_features.h"
+#include "base/feature_list.h"
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
 namespace {
 
 bool ShouldThemifyFaviconForEntryUrl(const GURL& url) {
@@ -31,7 +36,9 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Themify menu favicon for CrOS Terminal home page.
-  if (url.SchemeIs(content::kChromeUIUntrustedScheme)) {
+  if (!base::FeatureList::IsEnabled(
+          chromeos::features::kTerminalMultiProfile) &&
+      url.SchemeIs(content::kChromeUIUntrustedScheme)) {
     return url.host_piece() == chrome::kChromeUIUntrustedTerminalHost;
   }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/views/crostini/DIR_METADATA b/chrome/browser/ui/views/crostini/DIR_METADATA
index b3cd940..06e627f 100644
--- a/chrome/browser/ui/views/crostini/DIR_METADATA
+++ b/chrome/browser/ui/views/crostini/DIR_METADATA
@@ -1,3 +1 @@
-monorail {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
index 174bfc9..e01a62a 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
@@ -284,6 +284,9 @@
   resume_button_ =
       AddMainPageButton(DownloadCommands::RESUME,
                         l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_RESUME));
+  review_button_ =
+      AddMainPageButton(DownloadCommands::REVIEW,
+                        l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_REVIEW));
 
   subpage_icon_holder_ =
       AddChildView(std::make_unique<views::FlexLayoutView>());
@@ -365,6 +368,8 @@
                                DownloadCommands::BYPASS_DEEP_SCANNING);
   resume_button_->SetVisible(ui_info_.primary_button_command ==
                              DownloadCommands::RESUME);
+  review_button_->SetVisible(ui_info_.primary_button_command ==
+                             DownloadCommands::REVIEW);
   subpage_icon_->SetVisible(ui_info_.has_subpage);
   subpage_icon_->SetBorder(views::CreateEmptyBorder(
       gfx::Insets(ui_info_.has_subpage ? kDownloadSubpageIconMargin : 0)));
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h
index 54eabb5..9f24226 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.h
@@ -112,6 +112,7 @@
   raw_ptr<views::MdTextButton> scan_button_ = nullptr;
   raw_ptr<views::MdTextButton> open_now_button_ = nullptr;
   raw_ptr<views::MdTextButton> resume_button_ = nullptr;
+  raw_ptr<views::MdTextButton> review_button_ = nullptr;
   raw_ptr<views::FlexLayoutView> main_button_holder_ = nullptr;
 
   // The progress bar for in-progress downloads.
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 e830fbb..cd0e05f 100644
--- a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
+++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/monogram_utils.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
 #include "chrome/browser/ui/views/hover_button.h"
+#include "chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/platform_locale_settings.h"
 #include "components/image_fetcher/core/image_fetcher_impl.h"
@@ -49,7 +50,7 @@
 // The desired size of the avatars of user accounts.
 constexpr int kDesiredAvatarSize = 30;
 // The desired size of the icon of the identity provider.
-constexpr int kDesiredIconSize = 20;
+constexpr int kDesiredIdpIconSize = 20;
 // The size of the padding used at the top and bottom of the bubble.
 constexpr int kTopBottomPadding = 4;
 // The size of the horizontal padding between the bubble content and the edge of
@@ -91,15 +92,16 @@
         })");
 
 // A CanvasImageSource that fills a gray circle with a monogram.
-class LetterAvatarImageSkiaSource : public gfx::CanvasImageSource {
+class LetterCircleCroppedImageSkiaSource : public gfx::CanvasImageSource {
  public:
-  LetterAvatarImageSkiaSource(const std::u16string& letter, int size)
+  LetterCircleCroppedImageSkiaSource(const std::u16string& letter, int size)
       : gfx::CanvasImageSource(gfx::Size(size, size)), letter_(letter) {}
 
-  LetterAvatarImageSkiaSource(const LetterAvatarImageSkiaSource&) = delete;
-  LetterAvatarImageSkiaSource& operator=(const LetterAvatarImageSkiaSource&) =
-      delete;
-  ~LetterAvatarImageSkiaSource() override = default;
+  LetterCircleCroppedImageSkiaSource(
+      const LetterCircleCroppedImageSkiaSource&) = delete;
+  LetterCircleCroppedImageSkiaSource& operator=(
+      const LetterCircleCroppedImageSkiaSource&) = delete;
+  ~LetterCircleCroppedImageSkiaSource() override = default;
 
   void Draw(gfx::Canvas* canvas) override {
     monogram::DrawMonogramInCanvas(canvas, size().width(), size().width(),
@@ -110,27 +112,43 @@
   const std::u16string letter_;
 };
 
-// A CanvasImageSource that draws a circle cropped avatar.
-class AvatarImageSkiaSource : public gfx::CanvasImageSource {
+// A CanvasImageSource that:
+// 1) Applies an optional square center-crop.
+// 2) Resizes the cropped image (while maintaining the image's aspect ratio) to
+//    fit into the target canvas. If no center-crop was applied and the source
+//    image is rectangular, the image is resized so that
+//    `avatar` small edge size == `canvas_edge_size`.
+// 3) Circle center-crops the resized image.
+class CircleCroppedImageSkiaSource : public gfx::CanvasImageSource {
  public:
-  AvatarImageSkiaSource(gfx::ImageSkia avatar, int canvas_edge_size)
+  CircleCroppedImageSkiaSource(gfx::ImageSkia avatar,
+                               absl::optional<int> pre_resize_avatar_crop_size,
+                               int canvas_edge_size)
       : gfx::CanvasImageSource(gfx::Size(canvas_edge_size, canvas_edge_size)) {
-    // Resize `avatar` so that it completely fills the canvas.
-    float height_ratio = ((float)avatar.height() / (float)avatar.width());
     int scaled_width = canvas_edge_size;
     int scaled_height = canvas_edge_size;
-    if (height_ratio >= 1.0f)
-      scaled_height = floor(canvas_edge_size * height_ratio);
-    else
-      scaled_width = floor(canvas_edge_size / height_ratio);
+    if (pre_resize_avatar_crop_size) {
+      float avatar_scale =
+          (canvas_edge_size / (float)*pre_resize_avatar_crop_size);
+      scaled_width = floor(avatar.width() * avatar_scale);
+      scaled_height = floor(avatar.height() * avatar_scale);
+    } else {
+      // Resize `avatar` so that it completely fills the canvas.
+      float height_ratio = ((float)avatar.height() / (float)avatar.width());
+      if (height_ratio >= 1.0f)
+        scaled_height = floor(canvas_edge_size * height_ratio);
+      else
+        scaled_width = floor(canvas_edge_size / height_ratio);
+    }
     avatar_ = gfx::ImageSkiaOperations::CreateResizedImage(
         avatar, skia::ImageOperations::RESIZE_BEST,
         gfx::Size(scaled_width, scaled_height));
   }
 
-  AvatarImageSkiaSource(const AvatarImageSkiaSource&) = delete;
-  AvatarImageSkiaSource& operator=(const AvatarImageSkiaSource&) = delete;
-  ~AvatarImageSkiaSource() override = default;
+  CircleCroppedImageSkiaSource(const CircleCroppedImageSkiaSource&) = delete;
+  CircleCroppedImageSkiaSource& operator=(const CircleCroppedImageSkiaSource&) =
+      delete;
+  ~CircleCroppedImageSkiaSource() override = default;
 
   // CanvasImageSource override:
   void Draw(gfx::Canvas* canvas) override {
@@ -240,7 +258,8 @@
     // Show placeholder brand icon prior to brand icon being fetched so that
     // header text wrapping does not change when brand icon is fetched.
     auto image_view = std::make_unique<views::ImageView>();
-    image_view->SetImageSize(gfx::Size(kDesiredIconSize, kDesiredIconSize));
+    image_view->SetImageSize(
+        gfx::Size(kDesiredIdpIconSize, kDesiredIdpIconSize));
     image_view->SetProperty(views::kMarginsKey,
                             gfx::Insets().set_right(kLeftRightPadding));
     bubble_icon_view_ = header->AddChildView(image_view.release());
@@ -481,11 +500,12 @@
     std::u16string letter = account_name;
     if (letter.length() > 0)
       letter = base::i18n::ToUpper(account_name.substr(0, 1));
-    avatar = gfx::CanvasImageSource::MakeImageSkia<LetterAvatarImageSkiaSource>(
-        letter, kDesiredAvatarSize);
+    avatar = gfx::CanvasImageSource::MakeImageSkia<
+        LetterCircleCroppedImageSkiaSource>(letter, kDesiredAvatarSize);
   } else {
-    avatar = gfx::CanvasImageSource::MakeImageSkia<AvatarImageSkiaSource>(
-        image.AsImageSkia(), kDesiredAvatarSize);
+    avatar =
+        gfx::CanvasImageSource::MakeImageSkia<CircleCroppedImageSkiaSource>(
+            image.AsImageSkia(), absl::nullopt, kDesiredAvatarSize);
   }
   image_view->SetImage(avatar);
 }
@@ -495,9 +515,12 @@
     const image_fetcher::RequestMetadata& metadata) {
   if (bubble_icon_view_ != nullptr && image.Width() == image.Height() &&
       image.Width() >= AccountSelectionView::GetBrandIconMinimumSize()) {
-    gfx::ImageSkia resized_image = gfx::ImageSkiaOperations::CreateResizedImage(
-        image.AsImageSkia(), skia::ImageOperations::RESIZE_LANCZOS3,
-        gfx::Size(kDesiredIconSize, kDesiredIconSize));
+    gfx::ImageSkia resized_image =
+        gfx::CanvasImageSource::MakeImageSkia<CircleCroppedImageSkiaSource>(
+            image.AsImageSkia(),
+            image.Width() *
+                FedCmAccountSelectionView::kMaskableWebIconSafeZoneRatio,
+            kDesiredIdpIconSize);
     bubble_icon_view_->SetImage(resized_image);
   }
 }
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 ed1eb96a..0231d87 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
@@ -19,12 +19,17 @@
 
 // static
 int AccountSelectionView::GetBrandIconMinimumSize() {
-  return 20;
+  return 20 / FedCmAccountSelectionView::kMaskableWebIconSafeZoneRatio;
 }
 
 // static
 int AccountSelectionView::GetBrandIconIdealSize() {
-  return 20;
+  // As only a single brand icon is selected and the user can have monitors with
+  // different screen densities, make the ideal size be the size which works
+  // with a high density display (if the OS supports high density displays).
+  float max_supported_scale = ui::GetScaleForResourceScaleFactor(
+      ui::GetSupportedResourceScaleFactors().back());
+  return round(GetBrandIconMinimumSize() * max_supported_scale);
 }
 
 FedCmAccountSelectionView::FedCmAccountSelectionView(
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 f5ed11a..fd787b4 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
@@ -20,6 +20,10 @@
                                   TabStripModelObserver,
                                   views::WidgetObserver {
  public:
+  // safe_zone_diameter/icon_size as defined in
+  // https://www.w3.org/TR/appmanifest/#icon-masks
+  static constexpr float kMaskableWebIconSafeZoneRatio = 0.8f;
+
   explicit FedCmAccountSelectionView(AccountSelectionView::Delegate* delegate);
   ~FedCmAccountSelectionView() override;
 
diff --git a/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc b/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc
index d34520c..c945f77 100644
--- a/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc
+++ b/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc
@@ -182,10 +182,12 @@
 
   EXPECT_TRUE(app_browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP));
 
-  // No favicons shown for system apps.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  // No favicons shown for ash system apps.
   EXPECT_FALSE(
       app_browser_->tab_strip_model()->delegate()->ShouldDisplayFavicon(
           app_browser_->tab_strip_model()->GetActiveWebContents()));
+#endif
 
   // Tabbed PWAs only open URLs within the scope of the app. The manifest is
   // another URL besides |tabbed_app_url_| in scope.
diff --git a/chrome/browser/ui/web_applications/web_share_target_browsertest.cc b/chrome/browser/ui/web_applications/web_share_target_browsertest.cc
index 94b25975..86699705 100644
--- a/chrome/browser/ui/web_applications/web_share_target_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_share_target_browsertest.cc
@@ -255,14 +255,14 @@
 
     intent->mime_type = "text/csv";
     intent->files = std::vector<apps::mojom::IntentFilePtr>{};
-    for (size_t i = 0; i < file_paths.size(); i++) {
+    for (const base::FilePath& file_path : file_paths) {
       int64_t file_size = 0;
-      base::GetFileSize(file_paths[i], &file_size);
+      base::GetFileSize(file_path, &file_size);
       auto file = apps::mojom::IntentFile::New();
-      file->file_name = base::SafeBaseName::Create(file_paths[i]);
+      file->file_name = base::SafeBaseName::Create(file_path);
       file->file_size = file_size;
       file->mime_type = "text/csv";
-      file->url = net::FilePathToFileURL(file_paths[i]);
+      file->url = net::FilePathToFileURL(file_path);
       intent->files->push_back(std::move(file));
     }
     intent->action = apps_util::kIntentActionSendMultiple;
diff --git a/chrome/browser/ui/webid/account_selection_view.h b/chrome/browser/ui/webid/account_selection_view.h
index 2600017..e38835f 100644
--- a/chrome/browser/ui/webid/account_selection_view.h
+++ b/chrome/browser/ui/webid/account_selection_view.h
@@ -40,10 +40,12 @@
 
   static std::unique_ptr<AccountSelectionView> Create(Delegate* delegate);
 
-  // Returns the brand icon minimum size in dip.
+  // Returns the brand icon minimum size. This includes the size of the
+  // safe-zone defined in https://www.w3.org/TR/appmanifest/#icon-masks
   static int GetBrandIconMinimumSize();
 
-  // Returns the brand icon ideal size in dip.
+  // Returns the brand icon ideal size. This includes the size of the
+  // safe-zone defined in https://www.w3.org/TR/appmanifest/#icon-masks
   static int GetBrandIconIdealSize();
 
   explicit AccountSelectionView(Delegate* delegate) : delegate_(delegate) {}
diff --git a/chrome/browser/ui/webui/certificate_provisioning_ui_handler.cc b/chrome/browser/ui/webui/certificate_provisioning_ui_handler.cc
index b5911204..97aee29 100644
--- a/chrome/browser/ui/webui/certificate_provisioning_ui_handler.cc
+++ b/chrome/browser/ui/webui/certificate_provisioning_ui_handler.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/common/net/x509_certificate_model.h"
 #include "chrome/common/net/x509_certificate_model_nss.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/policy/core/browser/cloud/message_util.h"
diff --git a/chrome/browser/ui/webui/certificate_viewer_ui.cc b/chrome/browser/ui/webui/certificate_viewer_ui.cc
index dd638f3..c648644a 100644
--- a/chrome/browser/ui/webui/certificate_viewer_ui.cc
+++ b/chrome/browser/ui/webui/certificate_viewer_ui.cc
@@ -44,6 +44,7 @@
       {"hierarchy", IDS_CERT_DETAILS_CERTIFICATE_HIERARCHY_LABEL},
       {"certFields", IDS_CERT_DETAILS_CERTIFICATE_FIELDS_LABEL},
       {"certFieldVal", IDS_CERT_DETAILS_CERTIFICATE_FIELD_VALUE_LABEL},
+      {"certError", IDS_CERT_DUMP_ERROR},
   };
   html_source->AddLocalizedStrings(kStrings);
 
diff --git a/chrome/browser/ui/webui/certificate_viewer_webui.cc b/chrome/browser/ui/webui/certificate_viewer_webui.cc
index ee17209..518ce71 100644
--- a/chrome/browser/ui/webui/certificate_viewer_webui.cc
+++ b/chrome/browser/ui/webui/certificate_viewer_webui.cc
@@ -23,16 +23,21 @@
 #include "chrome/browser/ui/certificate_dialogs.h"
 #include "chrome/browser/ui/webui/certificate_viewer_ui.h"
 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
-#include "chrome/common/net/x509_certificate_model_nss.h"
+#include "chrome/common/net/x509_certificate_model.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/host_zoom_map.h"
 #include "content/public/browser/web_contents.h"
-#include "net/cert/x509_util_nss.h"
+#include "net/cert/x509_util.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/geometry/size.h"
 
+#if BUILDFLAG(USE_NSS_CERTS)
+#include "chrome/common/net/x509_certificate_model_nss.h"
+#include "net/cert/x509_util_nss.h"
+#endif
+
 using content::WebContents;
 using content::WebUIMessageHandler;
 
@@ -119,25 +124,56 @@
 void ShowCertificateViewer(WebContents* web_contents,
                            gfx::NativeWindow parent,
                            net::X509Certificate* cert) {
+  std::vector<std::string> nicknames;
+#if BUILDFLAG(USE_NSS_CERTS)
   net::ScopedCERTCertificateList nss_certs =
       net::x509_util::CreateCERTCertificateListFromX509Certificate(cert);
-  if (nss_certs.empty())
-    return;
+  // If any of the certs could not be parsed by NSS, |nss_certs| will be an
+  // empty list and |nicknames| will not be populated, which is fine as a
+  // fallback.
+  for (const auto& nss_cert : nss_certs) {
+    nicknames.push_back(x509_certificate_model::GetRawNickname(nss_cert.get()));
+  }
+#endif
 
-  CertificateViewerDialog::ShowConstrained(std::move(nss_certs), web_contents,
-                                           parent);
+  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> cert_buffers;
+  cert_buffers.push_back(bssl::UpRef(cert->cert_buffer()));
+  for (const auto& intermediate : cert->intermediate_buffers()) {
+    cert_buffers.push_back(bssl::UpRef(intermediate));
+  }
+  CertificateViewerDialog::ShowConstrained(
+      std::move(cert_buffers), std::move(nicknames), web_contents, parent);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // CertificateViewerDialog
 
+#if BUILDFLAG(USE_NSS_CERTS)
 // static
 CertificateViewerDialog* CertificateViewerDialog::ShowConstrained(
-    net::ScopedCERTCertificateList certs,
+    net::ScopedCERTCertificateList nss_certs,
     WebContents* web_contents,
     gfx::NativeWindow parent) {
+  std::vector<std::string> nicknames;
+  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> cert_buffers;
+  for (const auto& cert : nss_certs) {
+    nicknames.push_back(x509_certificate_model::GetRawNickname(cert.get()));
+    cert_buffers.push_back(net::x509_util::CreateCryptoBuffer(
+        base::make_span(cert->derCert.data, cert->derCert.len)));
+  }
+  return ShowConstrained(std::move(cert_buffers), std::move(nicknames),
+                         web_contents, parent);
+}
+#endif
+
+// static
+CertificateViewerDialog* CertificateViewerDialog::ShowConstrained(
+    std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs,
+    std::vector<std::string> cert_nicknames,
+    content::WebContents* web_contents,
+    gfx::NativeWindow parent) {
   CertificateViewerDialog* dialog_ptr =
-      new CertificateViewerDialog(std::move(certs));
+      new CertificateViewerDialog(std::move(certs), std::move(cert_nicknames));
   auto dialog = base::WrapUnique(dialog_ptr);
 
   // TODO(bshe): UI tweaks needed for Aura HTML Dialog, such as adding padding
@@ -160,13 +196,17 @@
 }
 
 CertificateViewerDialog::CertificateViewerDialog(
-    net::ScopedCERTCertificateList certs)
-    : nss_certs_(std::move(certs)) {
+    std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs,
+    std::vector<std::string> cert_nicknames) {
+  for (size_t i = 0; i < certs.size(); ++i) {
+    std::string nickname;
+    if (i < cert_nicknames.size())
+      nickname = std::move(cert_nicknames[i]);
+    certs_.emplace_back(std::move(certs[i]), std::move(nickname));
+  }
   // Construct the dialog title from the certificate.
   title_ = l10n_util::GetStringFUTF16(
-      IDS_CERT_INFO_DIALOG_TITLE,
-      base::UTF8ToUTF16(
-          x509_certificate_model::GetTitle(nss_certs_.front().get())));
+      IDS_CERT_INFO_DIALOG_TITLE, base::UTF8ToUTF16(certs_.front().GetTitle()));
 }
 
 CertificateViewerDialog::~CertificateViewerDialog() = default;
@@ -186,8 +226,7 @@
 void CertificateViewerDialog::GetWebUIMessageHandlers(
     std::vector<WebUIMessageHandler*>* handlers) const {
   handlers->push_back(new CertificateViewerDialogHandler(
-      const_cast<CertificateViewerDialog*>(this),
-      net::x509_util::DupCERTCertificateList(nss_certs_)));
+      const_cast<CertificateViewerDialog*>(this), &certs_));
 }
 
 void CertificateViewerDialog::GetDialogSize(gfx::Size* size) const {
@@ -196,72 +235,79 @@
   size->SetSize(kDefaultWidth, kDefaultHeight);
 }
 
+std::string HandleOptionalOrError(
+    const x509_certificate_model::OptionalStringOrError& s) {
+  if (absl::holds_alternative<x509_certificate_model::Error>(s))
+    return l10n_util::GetStringUTF8(IDS_CERT_DUMP_ERROR);
+  else if (absl::holds_alternative<x509_certificate_model::NotPresent>(s))
+    return l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT);
+  return absl::get<std::string>(s);
+}
+
 std::string CertificateViewerDialog::GetDialogArgs() const {
   std::string data;
 
   // Certificate information. The keys in this dictionary's general key
   // correspond to the IDs in the Html page.
   base::DictionaryValue cert_info;
-  CERTCertificate* cert_hnd = nss_certs_.front().get();
+  const x509_certificate_model::X509CertificateModel& model = certs_.front();
 
-  // Standard certificate details.
-  const std::string alternative_text =
-      l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT);
+  cert_info.SetBoolean("isError", !model.is_valid());
   cert_info.SetStringPath(
       "general.title",
-      l10n_util::GetStringFUTF8(
-          IDS_CERT_INFO_DIALOG_TITLE,
-          base::UTF8ToUTF16(x509_certificate_model::GetTitle(cert_hnd))));
+      l10n_util::GetStringFUTF8(IDS_CERT_INFO_DIALOG_TITLE,
+                                base::UTF8ToUTF16(model.GetTitle())));
 
-  // Issued to information.
-  cert_info.SetStringPath(
-      "general.issued-cn",
-      x509_certificate_model::GetSubjectCommonName(cert_hnd, alternative_text));
-  cert_info.SetStringPath(
-      "general.issued-o",
-      x509_certificate_model::GetSubjectOrgName(cert_hnd, alternative_text));
-  cert_info.SetStringPath("general.issued-ou",
-                          x509_certificate_model::GetSubjectOrgUnitName(
-                              cert_hnd, alternative_text));
+  if (model.is_valid()) {
+    // Standard certificate details.
+    const std::string alternative_text =
+        l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT);
 
-  // Issuer information.
-  cert_info.SetStringPath(
-      "general.issuer-cn",
-      x509_certificate_model::GetIssuerCommonName(cert_hnd, alternative_text));
-  cert_info.SetStringPath(
-      "general.issuer-o",
-      x509_certificate_model::GetIssuerOrgName(cert_hnd, alternative_text));
-  cert_info.SetStringPath(
-      "general.issuer-ou",
-      x509_certificate_model::GetIssuerOrgUnitName(cert_hnd, alternative_text));
+    // Issued to information.
+    cert_info.SetStringPath(
+        "general.issued-cn",
+        HandleOptionalOrError(model.GetSubjectCommonName()));
+    cert_info.SetStringPath("general.issued-o",
+                            HandleOptionalOrError(model.GetSubjectOrgName()));
+    cert_info.SetStringPath(
+        "general.issued-ou",
+        HandleOptionalOrError(model.GetSubjectOrgUnitName()));
 
-  // Validity period.
-  base::Time issued, expires;
-  std::string issued_str, expires_str;
-  if (x509_certificate_model::GetTimes(cert_hnd, &issued, &expires)) {
-    issued_str = base::UTF16ToUTF8(
-        base::TimeFormatFriendlyDateAndTime(issued));
-    expires_str = base::UTF16ToUTF8(
-        base::TimeFormatFriendlyDateAndTime(expires));
-  } else {
-    issued_str = alternative_text;
-    expires_str = alternative_text;
+    // Issuer information.
+    cert_info.SetStringPath("general.issuer-cn",
+                            HandleOptionalOrError(model.GetIssuerCommonName()));
+    cert_info.SetStringPath("general.issuer-o",
+                            HandleOptionalOrError(model.GetIssuerOrgName()));
+    cert_info.SetStringPath(
+        "general.issuer-ou",
+        HandleOptionalOrError(model.GetIssuerOrgUnitName()));
+
+    // Validity period.
+    base::Time issued, expires;
+    std::string issued_str, expires_str;
+    if (model.GetTimes(&issued, &expires)) {
+      issued_str =
+          base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(issued));
+      expires_str =
+          base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(expires));
+    } else {
+      issued_str = alternative_text;
+      expires_str = alternative_text;
+    }
+    cert_info.SetStringPath("general.issue-date", issued_str);
+    cert_info.SetStringPath("general.expiry-date", expires_str);
   }
-  cert_info.SetStringPath("general.issue-date", issued_str);
-  cert_info.SetStringPath("general.expiry-date", expires_str);
 
   cert_info.SetStringPath("general.sha256",
-                          x509_certificate_model::HashCertSHA256(cert_hnd));
-  cert_info.SetStringPath("general.sha1",
-                          x509_certificate_model::HashCertSHA1(cert_hnd));
+                          model.HashCertSHA256WithSeparators());
+  cert_info.SetStringPath("general.sha1", model.HashCertSHA1WithSeparators());
 
   // Certificate hierarchy is constructed from bottom up.
   base::Value children;
   int index = 0;
-  for (const auto& cert : nss_certs_) {
+  for (const auto& cert : certs_) {
     base::Value cert_node(base::Value::Type::DICTIONARY);
-    cert_node.SetKey("label",
-                     base::Value(x509_certificate_model::GetTitle(cert.get())));
+    cert_node.SetKey("label", base::Value(cert.GetTitle()));
     cert_node.SetPath({"payload", "index"}, base::Value(index));
     // Add the child from the previous iteration.
     if (!children.is_none())
@@ -302,8 +348,8 @@
 
 CertificateViewerDialogHandler::CertificateViewerDialogHandler(
     CertificateViewerDialog* dialog,
-    net::ScopedCERTCertificateList cert_chain)
-    : dialog_(dialog), cert_chain_(std::move(cert_chain)) {}
+    const std::vector<x509_certificate_model::X509CertificateModel>* certs)
+    : dialog_(dialog), certs_(certs) {}
 
 CertificateViewerDialogHandler::~CertificateViewerDialogHandler() {
 }
@@ -329,10 +375,14 @@
 
   gfx::NativeWindow window =
       platform_util::GetTopLevel(dialog_->GetNativeWebContentsModalDialog());
-  ShowCertExportDialog(web_ui()->GetWebContents(),
-                       window,
-                       cert_chain_.begin() + cert_index,
-                       cert_chain_.end());
+
+  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> export_certs;
+  for (const auto& cert : base::make_span(*certs_).subspan(cert_index)) {
+    export_certs.push_back(bssl::UpRef(cert.cert_buffer()));
+  }
+  ShowCertExportDialog(web_ui()->GetWebContents(), window,
+                       std::move(export_certs),
+                       (*certs_)[cert_index].GetTitle());
 }
 
 void CertificateViewerDialogHandler::HandleRequestCertificateFields(
@@ -343,118 +393,96 @@
   if (cert_index < 0)
     return;
 
-  CERTCertificate* cert = cert_chain_[cert_index].get();
+  const x509_certificate_model::X509CertificateModel& model =
+      (*certs_)[cert_index];
 
-  CertNodeBuilder version_node(IDS_CERT_DETAILS_VERSION);
-  std::string version = x509_certificate_model::GetVersion(cert);
-  if (!version.empty()) {
-    version_node.Payload(l10n_util::GetStringFUTF8(
-        IDS_CERT_DETAILS_VERSION_FORMAT, base::UTF8ToUTF16(version)));
-  }
+  CertNodeBuilder contents_builder(IDS_CERT_DETAILS_CERTIFICATE);
 
-  CertNodeBuilder issued_node_builder(IDS_CERT_DETAILS_NOT_BEFORE);
-  CertNodeBuilder expires_node_builder(IDS_CERT_DETAILS_NOT_AFTER);
-  base::Time issued, expires;
-  if (x509_certificate_model::GetTimes(cert, &issued, &expires)) {
-    issued_node_builder.Payload(base::UTF16ToUTF8(
-        base::TimeFormatShortDateAndTimeWithTimeZone(issued)));
-    expires_node_builder.Payload(base::UTF16ToUTF8(
-        base::TimeFormatShortDateAndTimeWithTimeZone(expires)));
-  }
-
-  x509_certificate_model::Extensions extensions;
-  x509_certificate_model::GetExtensions(
-      l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_CRITICAL),
-      l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_NON_CRITICAL),
-      cert, &extensions);
-
-  std::unique_ptr<base::DictionaryValue> details_extensions;
-  if (!extensions.empty()) {
-    CertNodeBuilder details_extensions_builder(IDS_CERT_DETAILS_EXTENSIONS);
-    for (const x509_certificate_model::Extension& extension : extensions) {
-      details_extensions_builder.Child(
-          CertNodeBuilder(extension.name).Payload(extension.value).Build());
+  if (model.is_valid()) {
+    CertNodeBuilder issued_node_builder(IDS_CERT_DETAILS_NOT_BEFORE);
+    CertNodeBuilder expires_node_builder(IDS_CERT_DETAILS_NOT_AFTER);
+    base::Time issued, expires;
+    if (model.GetTimes(&issued, &expires)) {
+      issued_node_builder.Payload(base::UTF16ToUTF8(
+          base::TimeFormatShortDateAndTimeWithTimeZone(issued)));
+      expires_node_builder.Payload(base::UTF16ToUTF8(
+          base::TimeFormatShortDateAndTimeWithTimeZone(expires)));
     }
-    details_extensions = details_extensions_builder.Build();
+
+    std::vector<x509_certificate_model::Extension> extensions =
+        model.GetExtensions(
+            l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_CRITICAL),
+            l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_NON_CRITICAL));
+
+    std::unique_ptr<base::DictionaryValue> details_extensions;
+    if (!extensions.empty()) {
+      CertNodeBuilder details_extensions_builder(IDS_CERT_DETAILS_EXTENSIONS);
+      for (const x509_certificate_model::Extension& extension : extensions) {
+        details_extensions_builder.Child(
+            CertNodeBuilder(extension.name).Payload(extension.value).Build());
+      }
+      details_extensions = details_extensions_builder.Build();
+    }
+
+    contents_builder
+        // Main certificate fields.
+        .Child(CertNodeBuilder(IDS_CERT_DETAILS_VERSION)
+                   .Payload(l10n_util::GetStringFUTF8(
+                       IDS_CERT_DETAILS_VERSION_FORMAT,
+                       base::UTF8ToUTF16(model.GetVersion())))
+                   .Build())
+        .Child(CertNodeBuilder(IDS_CERT_DETAILS_SERIAL_NUMBER)
+                   .Payload(model.GetSerialNumberHexified())
+                   .Build())
+        .Child(CertNodeBuilder(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG)
+                   .Payload(model.ProcessSecAlgorithmSignature())
+                   .Build())
+        .Child(CertNodeBuilder(IDS_CERT_DETAILS_ISSUER)
+                   .Payload(HandleOptionalOrError(model.GetIssuerName()))
+                   .Build())
+        // Validity period.
+        .Child(CertNodeBuilder(IDS_CERT_DETAILS_VALIDITY)
+                   .Child(issued_node_builder.Build())
+                   .Child(expires_node_builder.Build())
+                   .Build())
+        .Child(CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT)
+                   .Payload(HandleOptionalOrError(model.GetSubjectName()))
+                   .Build())
+        // Subject key information.
+        .Child(
+            CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT_KEY_INFO)
+                .Child(CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT_KEY_ALG)
+                           .Payload(model.ProcessSecAlgorithmSubjectPublicKey())
+                           .Build())
+                .Child(CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT_KEY)
+                           .Payload(model.ProcessSubjectPublicKeyInfo())
+                           .Build())
+                .Build())
+        // Extensions.
+        .ChildIfNotNull(std::move(details_extensions))
+        .Child(CertNodeBuilder(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG)
+                   .Payload(model.ProcessSecAlgorithmSignatureWrap())
+                   .Build())
+        .Child(CertNodeBuilder(IDS_CERT_DETAILS_CERTIFICATE_SIG_VALUE)
+                   .Payload(model.ProcessRawBitsSignatureWrap())
+                   .Build());
   }
 
+  contents_builder.Child(
+      CertNodeBuilder(IDS_CERT_INFO_FINGERPRINTS_GROUP)
+          .Child(CertNodeBuilder(IDS_CERT_INFO_SHA256_FINGERPRINT_LABEL)
+                     .Payload(model.HashCertSHA256WithSeparators())
+                     .Build())
+          .Child(CertNodeBuilder(IDS_CERT_INFO_SHA1_FINGERPRINT_LABEL)
+                     .Payload(model.HashCertSHA1WithSeparators())
+                     .Build())
+          .Build());
+
   base::ListValue root_list;
-  root_list.Append(base::Value::FromUniquePtrValue(
-      CertNodeBuilder(x509_certificate_model::GetTitle(cert))
-          .Child(
-              CertNodeBuilder(
-                  l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE))
-                  // Main certificate fields.
-                  .Child(version_node.Build())
-                  .Child(
-                      CertNodeBuilder(IDS_CERT_DETAILS_SERIAL_NUMBER)
-                          .Payload(
-                              x509_certificate_model::GetSerialNumberHexified(
-                                  cert, l10n_util::GetStringUTF8(
-                                            IDS_CERT_INFO_FIELD_NOT_PRESENT)))
-                          .Build())
-                  .Child(CertNodeBuilder(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG)
-                             .Payload(x509_certificate_model::
-                                          ProcessSecAlgorithmSignature(cert))
-                             .Build())
-                  .Child(
-                      CertNodeBuilder(IDS_CERT_DETAILS_ISSUER)
-                          .Payload(x509_certificate_model::GetIssuerName(cert))
-                          .Build())
-                  // Validity period.
-                  .Child(CertNodeBuilder(IDS_CERT_DETAILS_VALIDITY)
-                             .Child(issued_node_builder.Build())
-                             .Child(expires_node_builder.Build())
-                             .Build())
-                  .Child(
-                      CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT)
-                          .Payload(x509_certificate_model::GetSubjectName(cert))
-                          .Build())
-                  // Subject key information.
-                  .Child(
-                      CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT_KEY_INFO)
-                          .Child(
-                              CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT_KEY_ALG)
-                                  .Payload(
-                                      x509_certificate_model::
-                                          ProcessSecAlgorithmSubjectPublicKey(
-                                              cert))
-                                  .Build())
-                          .Child(CertNodeBuilder(IDS_CERT_DETAILS_SUBJECT_KEY)
-                                     .Payload(
-                                         x509_certificate_model::
-                                             ProcessSubjectPublicKeyInfo(cert))
-                                     .Build())
-                          .Build())
-                  // Extensions.
-                  .ChildIfNotNull(std::move(details_extensions))
-                  .Child(
-                      CertNodeBuilder(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG)
-                          .Payload(x509_certificate_model::
-                                       ProcessSecAlgorithmSignatureWrap(cert))
-                          .Build())
-                  .Child(CertNodeBuilder(IDS_CERT_DETAILS_CERTIFICATE_SIG_VALUE)
-                             .Payload(x509_certificate_model::
-                                          ProcessRawBitsSignatureWrap(cert))
-                             .Build())
-                  .Child(
-                      CertNodeBuilder(IDS_CERT_INFO_FINGERPRINTS_GROUP)
-                          .Child(CertNodeBuilder(
-                                     IDS_CERT_INFO_SHA256_FINGERPRINT_LABEL)
-                                     .Payload(
-                                         x509_certificate_model::HashCertSHA256(
-                                             cert))
-                                     .Build())
-                          .Child(
-                              CertNodeBuilder(
-                                  IDS_CERT_INFO_SHA1_FINGERPRINT_LABEL)
-                                  .Payload(x509_certificate_model::HashCertSHA1(
-                                      cert))
-                                  .Build())
-                          .Build())
-                  .Build())
-          .Build()));
-
+  root_list.Append(
+      base::Value::FromUniquePtrValue(CertNodeBuilder(model.GetTitle())
+                                          .Child(contents_builder.Build())
+                                          .Build()));
   // Send certificate information to javascript.
   ResolveJavascriptCallback(callback_id, root_list);
 }
@@ -462,7 +490,7 @@
 int CertificateViewerDialogHandler::GetCertificateIndex(
     int requested_index) const {
   int cert_index = requested_index;
-  if (cert_index < 0 || cert_index >= static_cast<int>(cert_chain_.size()))
+  if (cert_index < 0 || static_cast<size_t>(cert_index) >= certs_->size())
     return -1;
   return cert_index;
 }
diff --git a/chrome/browser/ui/webui/certificate_viewer_webui.h b/chrome/browser/ui/webui/certificate_viewer_webui.h
index 70cc1c95..f9c5659 100644
--- a/chrome/browser/ui/webui/certificate_viewer_webui.h
+++ b/chrome/browser/ui/webui/certificate_viewer_webui.h
@@ -9,26 +9,41 @@
 #include <vector>
 
 #include "base/values.h"
+#include "chrome/common/net/x509_certificate_model.h"
 #include "content/public/browser/web_ui_message_handler.h"
-#include "net/cert/scoped_nss_types.h"
+#include "crypto/crypto_buildflags.h"
 #include "net/cert/x509_certificate.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/web_dialogs/web_dialog_delegate.h"
 
+#if BUILDFLAG(USE_NSS_CERTS)
+#include "net/cert/scoped_nss_types.h"
+#endif
+
 namespace content {
 class WebContents;
 }
 
 class ConstrainedWebDialogDelegate;
 
+// TODO(https://crbug.com/953425): Update comment when this is used by other
+// platforms.
 // Dialog for displaying detailed certificate information. This is used in linux
 // and chromeos builds to display detailed information in a floating dialog when
 // the user clicks on "Certificate Information" from the lock icon of a web site
 // or "View" from the Certificate Manager.
 class CertificateViewerDialog : public ui::WebDialogDelegate {
  public:
+#if BUILDFLAG(USE_NSS_CERTS)
   static CertificateViewerDialog* ShowConstrained(
-      net::ScopedCERTCertificateList certs,
+      net::ScopedCERTCertificateList nss_certs,
+      content::WebContents* web_contents,
+      gfx::NativeWindow parent);
+#endif
+
+  static CertificateViewerDialog* ShowConstrained(
+      std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs,
+      std::vector<std::string> cert_nicknames,
       content::WebContents* web_contents,
       gfx::NativeWindow parent);
 
@@ -45,7 +60,8 @@
   // Construct a certificate viewer for the passed in certificate. A reference
   // to the certificate pointer is added for the lifetime of the certificate
   // viewer.
-  explicit CertificateViewerDialog(net::ScopedCERTCertificateList certs);
+  CertificateViewerDialog(std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs,
+                          std::vector<std::string> cert_nicknames);
 
   // ui::WebDialogDelegate:
   ui::ModalType GetDialogModalType() const override;
@@ -61,8 +77,7 @@
                        bool* out_close_dialog) override;
   bool ShouldShowDialogTitle() const override;
 
-  // The certificate chain, as NSS cert objects.
-  net::ScopedCERTCertificateList nss_certs_;
+  std::vector<x509_certificate_model::X509CertificateModel> certs_;
 
   // The title of the certificate viewer dialog, Certificate Viewer: CN.
   std::u16string title_;
@@ -75,8 +90,9 @@
 // details and export the certificate.
 class CertificateViewerDialogHandler : public content::WebUIMessageHandler {
  public:
-  CertificateViewerDialogHandler(CertificateViewerDialog* dialog,
-                                 net::ScopedCERTCertificateList cert_chain);
+  CertificateViewerDialogHandler(
+      CertificateViewerDialog* dialog,
+      const std::vector<x509_certificate_model::X509CertificateModel>* certs);
 
   CertificateViewerDialogHandler(const CertificateViewerDialogHandler&) =
       delete;
@@ -109,8 +125,7 @@
   // The dialog.
   CertificateViewerDialog* dialog_;
 
-  // The certificate chain.
-  net::ScopedCERTCertificateList cert_chain_;
+  const std::vector<x509_certificate_model::X509CertificateModel>* certs_;
 };
 
 #endif  // CHROME_BROWSER_UI_WEBUI_CERTIFICATE_VIEWER_WEBUI_H_
diff --git a/chrome/browser/ui/webui/chromeos/crostini_installer/DIR_METADATA b/chrome/browser/ui/webui/chromeos/crostini_installer/DIR_METADATA
index b3cd940..06e627f 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_installer/DIR_METADATA
+++ b/chrome/browser/ui/webui/chromeos/crostini_installer/DIR_METADATA
@@ -1,3 +1 @@
-monorail {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/DIR_METADATA b/chrome/browser/ui/webui/chromeos/crostini_upgrader/DIR_METADATA
index b3cd940..06e627f 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/DIR_METADATA
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/DIR_METADATA
@@ -1,3 +1 @@
-monorail {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/ui/webui/chromeos/guest_os_installer/DIR_METADATA b/chrome/browser/ui/webui/chromeos/guest_os_installer/DIR_METADATA
index b3cd940..06e627f 100644
--- a/chrome/browser/ui/webui/chromeos/guest_os_installer/DIR_METADATA
+++ b/chrome/browser/ui/webui/chromeos/guest_os_installer/DIR_METADATA
@@ -1,3 +1 @@
-monorail {
-  component: "UI>Shell>Containers"
-}
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/ui/webui/favicon_source_unittest.cc b/chrome/browser/ui/webui/favicon_source_unittest.cc
index 9207a27..e876c54 100644
--- a/chrome/browser/ui/webui/favicon_source_unittest.cc
+++ b/chrome/browser/ui/webui/favicon_source_unittest.cc
@@ -266,8 +266,8 @@
   source()->StartDataRequest(
       GURL(base::StrCat(
           {kDummyPrefix,
-           "?size=16&scale_factor=1x&page_url=https%3A%2F%2Fwww.google."
-           "com&allow_google_server_fallback=0"})),
+           "?size=16&scale_factor=1x&pageUrl=https%3A%2F%2Fwww.google."
+           "com&allowGoogleServerFallback=0"})),
       test_web_contents_getter_, base::BindOnce(&Noop));
 }
 
@@ -283,8 +283,8 @@
   source()->StartDataRequest(
       GURL(base::StrCat(
           {kDummyPrefix,
-           "?size=16&scale_factor=1x&page_url=https%3A%2F%2Fwww.google."
-           "com&allow_google_server_fallback=1"})),
+           "?size=16&scale_factor=1x&pageUrl=https%3A%2F%2Fwww.google."
+           "com&allowGoogleServerFallback=1"})),
       test_web_contents_getter_, base::BindOnce(&Noop));
 }
 
@@ -301,8 +301,8 @@
   source()->StartDataRequest(
       GURL(base::StrCat(
           {kDummyPrefix,
-           "?size=16&scale_factor=1x&page_url=https%3A%2F%2Fwww.google."
-           "com&allow_google_server_fallback=1"})),
+           "?size=16&scale_factor=1x&pageUrl=https%3A%2F%2Fwww.google."
+           "com&allowGoogleServerFallback=1"})),
       test_web_contents_getter_, base::BindOnce(&Noop));
 }
 
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc
index f784ec4..1c09def 100644
--- a/chrome/browser/ui/webui/settings/about_handler.cc
+++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include <limits>
 #include <string>
 
 #include "base/bind.h"
@@ -49,6 +50,8 @@
 #include "v8/include/v8-version-string.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/components/fwupd/firmware_update_manager.h"
+#include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
 #include "base/i18n/time_formatting.h"
 #include "chrome/browser/ash/arc/arc_util.h"
@@ -294,6 +297,11 @@
                           base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
+      "getFirmwareUpdateCount",
+      base::BindRepeating(&AboutHandler::HandleGetFirmwareUpdateCount,
+                          base::Unretained(this)));
+
+  web_ui()->RegisterMessageCallback(
       "openOsHelpPage", base::BindRepeating(&AboutHandler::HandleOpenOsHelpPage,
                                             base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
@@ -532,6 +540,17 @@
   ResolveJavascriptCallback(base::Value(callback_id), *version_info);
 }
 
+void AboutHandler::HandleGetFirmwareUpdateCount(const base::Value::List& args) {
+  DCHECK(base::FeatureList::IsEnabled(chromeos::features::kFirmwareUpdaterApp));
+  CHECK_EQ(1U, args.size());
+  const std::string& callback_id = args[0].GetString();
+  auto* firmware_update_manager = ash::FirmwareUpdateManager::Get();
+  size_t update_count = firmware_update_manager->GetUpdateCount();
+  DCHECK_LT(update_count, std::numeric_limits<int>::max());
+  ResolveJavascriptCallback(base::Value(callback_id),
+                            base::Value(static_cast<int>(update_count)));
+}
+
 void AboutHandler::HandleGetRegulatoryInfo(const base::Value::List& args) {
   CHECK_EQ(1U, args.size());
   const std::string& callback_id = args[0].GetString();
diff --git a/chrome/browser/ui/webui/settings/about_handler.h b/chrome/browser/ui/webui/settings/about_handler.h
index 1990ef0..16e63ed 100644
--- a/chrome/browser/ui/webui/settings/about_handler.h
+++ b/chrome/browser/ui/webui/settings/about_handler.h
@@ -106,6 +106,9 @@
       std::string callback_id,
       std::unique_ptr<base::DictionaryValue> version_info);
 
+  // Retrieves the number of firmware updates available.
+  void HandleGetFirmwareUpdateCount(const base::Value::List& args);
+
   // Retrieves channel info.
   void HandleGetChannelInfo(const base::Value::List& args);
 
diff --git a/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc b/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
index 70a5a8d..f1d3de0 100644
--- a/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
+++ b/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
@@ -22,7 +22,6 @@
       content::WebUIDataSource::Create(chrome::kChromeUIUsbInternalsHost);
 
   static constexpr webui::ResourcePath kPaths[] = {
-      {"usb_device.mojom-webui.js", IDR_USB_DEVICE_MOJOM_WEBUI_JS},
       {"usb_enumeration_options.mojom-webui.js",
        IDR_USB_ENUMERATION_OPTIONS_MOJOM_WEBUI_JS},
       {"usb_manager.mojom-webui.js", IDR_USB_DEVICE_MANAGER_MOJOM_WEBUI_JS},
diff --git a/chrome/browser/usb/android/BUILD.gn b/chrome/browser/usb/android/BUILD.gn
index 0d0900a..703d81a 100644
--- a/chrome/browser/usb/android/BUILD.gn
+++ b/chrome/browser/usb/android/BUILD.gn
@@ -41,12 +41,9 @@
   sources = [ "java/src/org/chromium/chrome/browser/usb/UsbBridge.java" ]
 }
 
-android_library("junit") {
+robolectric_library("junit") {
   testonly = true
 
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
-
   sources = [
     "junit/src/org/chromium/chrome/browser/usb/UsbNotificationManagerTest.java",
   ]
diff --git a/chrome/browser/util/BUILD.gn b/chrome/browser/util/BUILD.gn
index c0585e4..d860049 100644
--- a/chrome/browser/util/BUILD.gn
+++ b/chrome/browser/util/BUILD.gn
@@ -36,9 +36,7 @@
   ]
 }
 
-java_library("junit_tests") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit_tests") {
   testonly = true
   sources = [
     "android/java/src/org/chromium/chrome/browser/util/ChromeFileProviderTest.java",
diff --git a/chrome/browser/video_tutorials/internal/BUILD.gn b/chrome/browser/video_tutorials/internal/BUILD.gn
index 250637d..7cd9672 100644
--- a/chrome/browser/video_tutorials/internal/BUILD.gn
+++ b/chrome/browser/video_tutorials/internal/BUILD.gn
@@ -144,9 +144,7 @@
     ]
   }
 
-  java_library("junit") {
-    # Skip platform checks since Robolectric depends on requires_android targets.
-    bypass_platform_checks = true
+  robolectric_library("junit") {
     testonly = true
     sources = [
       "android/java/src/org/chromium/chrome/browser/video_tutorials/PlaybackStateObserverUnitTest.java",
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index 4ce0f9ef..cd4064b 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -261,6 +261,7 @@
     "//chrome/app/theme:chrome_unscaled_resources",
     "//chrome/browser:browser_process",
     "//chrome/browser/ash/system_web_apps/types:types",
+    "//chrome/browser/favicon",
     "//chrome/browser/profiles:profile",
     "//chrome/common",
     "//chrome/common:non_code_constants",
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc
index 929a202..60b8499 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc
@@ -155,13 +155,13 @@
   std::vector<ProtocolHandler> handlers =
       protocol_handler_manager().GetAllowedHandlersForProtocol("web+test");
   ASSERT_EQ(handlers.size(), 2U);
-  for (size_t i = 0; i < handlers.size(); i++) {
-    ASSERT_EQ(handlers[i].protocol(), "web+test");
-    if (handlers[i].web_app_id() == app_id1) {
-      ASSERT_EQ(handlers[i].url(), GURL("http://example.com/test=%s"));
+  for (const ProtocolHandler& handler : handlers) {
+    ASSERT_EQ(handler.protocol(), "web+test");
+    if (handler.web_app_id() == app_id1) {
+      ASSERT_EQ(handler.url(), GURL("http://example.com/test=%s"));
     } else {
-      ASSERT_EQ(handlers[i].web_app_id(), app_id2);
-      ASSERT_EQ(handlers[i].url(), GURL("http://example2.com/test=%s"));
+      ASSERT_EQ(handler.web_app_id(), app_id2);
+      ASSERT_EQ(handler.url(), GURL("http://example2.com/test=%s"));
     }
   }
 }
@@ -180,13 +180,13 @@
   std::vector<ProtocolHandler> handlers =
       protocol_handler_manager().GetDisallowedHandlersForProtocol("web+test");
   ASSERT_EQ(handlers.size(), 2U);
-  for (size_t i = 0; i < handlers.size(); i++) {
-    ASSERT_EQ(handlers[i].protocol(), "web+test");
-    if (handlers[i].web_app_id() == app_id1) {
-      ASSERT_EQ(handlers[i].url(), GURL("http://example.com/test=%s"));
+  for (const ProtocolHandler& handler : handlers) {
+    ASSERT_EQ(handler.protocol(), "web+test");
+    if (handler.web_app_id() == app_id1) {
+      ASSERT_EQ(handler.url(), GURL("http://example.com/test=%s"));
     } else {
-      ASSERT_EQ(handlers[i].web_app_id(), app_id2);
-      ASSERT_EQ(handlers[i].url(), GURL("http://example2.com/test=%s"));
+      ASSERT_EQ(handler.web_app_id(), app_id2);
+      ASSERT_EQ(handler.url(), GURL("http://example2.com/test=%s"));
     }
   }
 }
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 5f6f618..61d8ae2 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1655143190-64a01d76c010eded6896d98f91512b9408259d86.profdata
+chrome-linux-main-1655164791-18e6fd177a246ef7b609b32c2d650d6b06eb8498.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index ae568e6..a030780 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1655143190-6694e59a3bceda75f6351998159031271226c552.profdata
+chrome-mac-main-1655164791-b6f6fe3721916cbd75123234044b076b843e3f40.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 01a11c1..b4e2c201 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1655132339-aac254883e60e54814abe2887dd0065cfed9f6dc.profdata
+chrome-win32-main-1655164791-c01d6ce7664ddee09d1b906cfe78f33b2a5c1e98.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index c2eac53..ec7edb50 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1655132339-d3bbd175507fbedc3cda789ac9d637ffa3eccd7c.profdata
+chrome-win64-main-1655164791-0521113a218b6057c7ca0cc533f21cf570a12521.profdata
diff --git a/chrome/common/net/x509_certificate_model.cc b/chrome/common/net/x509_certificate_model.cc
index 8c7b7287..b93adb2 100644
--- a/chrome/common/net/x509_certificate_model.cc
+++ b/chrome/common/net/x509_certificate_model.cc
@@ -1199,6 +1199,9 @@
   parsed_successfully_ = true;
 }
 
+X509CertificateModel::X509CertificateModel(X509CertificateModel&& other) =
+    default;
+
 X509CertificateModel::~X509CertificateModel() = default;
 
 std::string X509CertificateModel::HashCertSHA256() const {
diff --git a/chrome/common/net/x509_certificate_model.h b/chrome/common/net/x509_certificate_model.h
index 8ee7389..3a52e589 100644
--- a/chrome/common/net/x509_certificate_model.h
+++ b/chrome/common/net/x509_certificate_model.h
@@ -34,6 +34,8 @@
   // nickname for the certificate, if available.
   X509CertificateModel(bssl::UniquePtr<CRYPTO_BUFFER> cert_data,
                        std::string nickname);
+  X509CertificateModel(X509CertificateModel&& other);
+  X509CertificateModel& operator=(X509CertificateModel&& other) = default;
   ~X509CertificateModel();
 
   // ---------------------------------------------------------------------------
diff --git a/chrome/common/net/x509_certificate_model_nss.cc b/chrome/common/net/x509_certificate_model_nss.cc
index 8f374648..fd755732 100644
--- a/chrome/common/net/x509_certificate_model_nss.cc
+++ b/chrome/common/net/x509_certificate_model_nss.cc
@@ -6,33 +6,17 @@
 
 #include <cert.h>
 #include <certt.h>
-#include <hasht.h>
-#include <keyhi.h>  // SECKEY_DestroyPrivateKey
-#include <keythi.h>  // SECKEYPrivateKey
-#include <pk11pub.h>  // PK11_FindKeyByAnyCert
-#include <seccomon.h>  // SECItem
-#include <sechash.h>
 #include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-#include <unicode/uidna.h>
 
 #include <algorithm>
 #include <memory>
 #include <tuple>
 
-#include "base/logging.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/grit/generated_resources.h"
 #include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h"
 #include "chrome/third_party/mozilla_security_manager/nsNSSCertificate.h"
-#include "crypto/nss_key_util.h"
 #include "crypto/nss_util.h"
 #include "crypto/scoped_nss_types.h"
 #include "net/cert/x509_util_nss.h"
-#include "ui/base/l10n/l10n_util.h"
 
 namespace psm = mozilla_security_manager;
 
@@ -49,38 +33,6 @@
   return s;
 }
 
-// Hash a certificate using the given algorithm, return the result as a
-// colon-seperated hex string.  The len specified is the number of bytes
-// required for storing the raw fingerprint.
-// (It's a bit redundant that the caller needs to specify len in addition to the
-// algorithm, but given the limited uses, not worth fixing.)
-std::string HashCert(CERTCertificate* cert, HASH_HashType algorithm, int len) {
-  unsigned char fingerprint[HASH_LENGTH_MAX];
-
-  DCHECK(NULL != cert->derCert.data);
-  DCHECK_NE(0U, cert->derCert.len);
-  DCHECK_LE(len, HASH_LENGTH_MAX);
-  memset(fingerprint, 0, len);
-  SECStatus rv = HASH_HashBuf(algorithm, fingerprint, cert->derCert.data,
-                              cert->derCert.len);
-  DCHECK_EQ(rv, SECSuccess);
-  return x509_certificate_model::ProcessRawBytes(fingerprint, len);
-}
-
-std::string ProcessSecAlgorithmInternal(SECAlgorithmID* algorithm_id) {
-  return psm::GetOIDText(&algorithm_id->algorithm);
-}
-
-std::string ProcessExtension(
-    const std::string& critical_label,
-    const std::string& non_critical_label,
-    CERTCertExtension* extension) {
-  std::string criticality =
-      extension->critical.data && extension->critical.data[0] ?
-          critical_label : non_critical_label;
-  return criticality + "\n" + psm::ProcessExtensionData(extension);
-}
-
 std::string GetNickname(CERTCertificate* cert_handle) {
   std::string name;
   if (cert_handle->nickname) {
@@ -100,6 +52,13 @@
 
 using std::string;
 
+std::string GetRawNickname(CERTCertificate* cert_handle) {
+  if (cert_handle->nickname) {
+    return cert_handle->nickname;
+  }
+  return std::string();
+}
+
 string GetCertNameOrNickname(CERTCertificate* cert_handle) {
   string name = ProcessIDN(
       Stringize(CERT_GetCommonName(&cert_handle->subject), std::string()));
@@ -108,76 +67,19 @@
   return GetNickname(cert_handle);
 }
 
-string GetVersion(CERTCertificate* cert_handle) {
-  // If the version field is omitted from the certificate, the default
-  // value is v1(0).
-  unsigned long version = 0;
-  if (cert_handle->version.len == 0 ||
-      SEC_ASN1DecodeInteger(&cert_handle->version, &version) == SECSuccess) {
-    return base::NumberToString(base::strict_cast<uint64_t>(version + 1));
-  }
-  return std::string();
-}
-
 net::CertType GetType(CERTCertificate* cert_handle) {
   return psm::GetCertType(cert_handle);
 }
 
-string GetSerialNumberHexified(CERTCertificate* cert_handle,
-                               const string& alternative_text) {
-  return Stringize(CERT_Hexify(&cert_handle->serialNumber, true),
-                   alternative_text);
-}
-
-string GetIssuerCommonName(CERTCertificate* cert_handle,
-                           const string& alternative_text) {
-  return Stringize(CERT_GetCommonName(&cert_handle->issuer), alternative_text);
-}
-
-string GetIssuerOrgName(CERTCertificate* cert_handle,
-                        const string& alternative_text) {
-  return Stringize(CERT_GetOrgName(&cert_handle->issuer), alternative_text);
-}
-
-string GetIssuerOrgUnitName(CERTCertificate* cert_handle,
-                            const string& alternative_text) {
-  return Stringize(CERT_GetOrgUnitName(&cert_handle->issuer), alternative_text);
-}
-
 string GetSubjectOrgName(CERTCertificate* cert_handle,
                          const string& alternative_text) {
   return Stringize(CERT_GetOrgName(&cert_handle->subject), alternative_text);
 }
 
-string GetSubjectOrgUnitName(CERTCertificate* cert_handle,
-                             const string& alternative_text) {
-  return Stringize(CERT_GetOrgUnitName(&cert_handle->subject),
-                   alternative_text);
-}
-
-string GetSubjectCommonName(CERTCertificate* cert_handle,
-                            const string& alternative_text) {
-  return Stringize(CERT_GetCommonName(&cert_handle->subject), alternative_text);
-}
-
-bool GetTimes(CERTCertificate* cert_handle,
-              base::Time* issued,
-              base::Time* expires) {
-  return net::x509_util::GetValidityTimes(cert_handle, issued, expires);
-}
-
 string GetTitle(CERTCertificate* cert_handle) {
   return psm::GetCertTitle(cert_handle);
 }
 
-string GetIssuerName(CERTCertificate* cert_handle) {
-  return psm::ProcessName(&cert_handle->issuer);
-}
-
-string GetSubjectName(CERTCertificate* cert_handle) {
-  return psm::ProcessName(&cert_handle->subject);
-}
-
 std::string GetIssuerDisplayName(CERTCertificate* cert_handle) {
   return net::x509_util::GetCERTNameDisplayName(&cert_handle->issuer);
 }
@@ -186,50 +88,4 @@
   return net::x509_util::GetCERTNameDisplayName(&cert_handle->subject);
 }
 
-void GetExtensions(const string& critical_label,
-                   const string& non_critical_label,
-                   CERTCertificate* cert_handle,
-                   Extensions* extensions) {
-  if (cert_handle->extensions) {
-    for (size_t i = 0; cert_handle->extensions[i] != NULL; ++i) {
-      Extension extension;
-      extension.name = psm::GetOIDText(&cert_handle->extensions[i]->id);
-      extension.value = ProcessExtension(
-          critical_label, non_critical_label, cert_handle->extensions[i]);
-      extensions->push_back(extension);
-    }
-  }
-}
-
-string HashCertSHA256(CERTCertificate* cert_handle) {
-  return HashCert(cert_handle, HASH_AlgSHA256, SHA256_LENGTH);
-}
-
-string HashCertSHA1(CERTCertificate* cert_handle) {
-  return HashCert(cert_handle, HASH_AlgSHA1, SHA1_LENGTH);
-}
-
-string ProcessSecAlgorithmSignature(CERTCertificate* cert_handle) {
-  return ProcessSecAlgorithmInternal(&cert_handle->signature);
-}
-
-string ProcessSecAlgorithmSubjectPublicKey(CERTCertificate* cert_handle) {
-  return ProcessSecAlgorithmInternal(
-      &cert_handle->subjectPublicKeyInfo.algorithm);
-}
-
-string ProcessSecAlgorithmSignatureWrap(CERTCertificate* cert_handle) {
-  return ProcessSecAlgorithmInternal(
-      &cert_handle->signatureWrap.signatureAlgorithm);
-}
-
-string ProcessSubjectPublicKeyInfo(CERTCertificate* cert_handle) {
-  return psm::ProcessSubjectPublicKeyInfo(&cert_handle->subjectPublicKeyInfo);
-}
-
-string ProcessRawBitsSignatureWrap(CERTCertificate* cert_handle) {
-  return ProcessRawBits(cert_handle->signatureWrap.signature.data,
-                        cert_handle->signatureWrap.signature.len);
-}
-
 }  // namespace x509_certificate_model
diff --git a/chrome/common/net/x509_certificate_model_nss.h b/chrome/common/net/x509_certificate_model_nss.h
index 123cb014..f42197a 100644
--- a/chrome/common/net/x509_certificate_model_nss.h
+++ b/chrome/common/net/x509_certificate_model_nss.h
@@ -8,82 +8,34 @@
 #include <stddef.h>
 
 #include <string>
-#include <vector>
 
-#include "base/containers/span.h"
 #include "chrome/common/net/x509_certificate_model.h"
 #include "net/cert/cert_type.h"
-#include "net/cert/scoped_nss_types.h"
 
 typedef struct CERTCertificateStr CERTCertificate;
 
-namespace base {
-class Time;
-}
-
 // This namespace defines a set of functions to be used in UI-related bits of
 // X509 certificates.
 namespace x509_certificate_model {
 
+// Returns the NSS nickname field of the certificate without processing. This
+// will generally be of the form "<token name> : <nickname>" but it's not
+// really documented in NSS.
+std::string GetRawNickname(CERTCertificate* cert_handle);
+
+// Returns the commonName of the certificate, or if that is empty, returns the
+// NSS certificate nickname (without the token name).
 std::string GetCertNameOrNickname(CERTCertificate* cert_handle);
 
-std::string GetVersion(CERTCertificate* cert_handle);
-
 net::CertType GetType(CERTCertificate* cert_handle);
 
-std::string GetSerialNumberHexified(CERTCertificate* cert_handle,
-                                    const std::string& alternative_text);
-
-std::string GetIssuerCommonName(CERTCertificate* cert_handle,
-                                const std::string& alternative_text);
-
-std::string GetIssuerOrgName(CERTCertificate* cert_handle,
-                             const std::string& alternative_text);
-
-std::string GetIssuerOrgUnitName(CERTCertificate* cert_handle,
-                                 const std::string& alternative_text);
-
 std::string GetSubjectOrgName(CERTCertificate* cert_handle,
                               const std::string& alternative_text);
 
-std::string GetSubjectOrgUnitName(CERTCertificate* cert_handle,
-                                  const std::string& alternative_text);
-
-std::string GetSubjectCommonName(CERTCertificate* cert_handle,
-                                 const std::string& alternative_text);
-
 std::string GetIssuerDisplayName(CERTCertificate* cert_handle);
 std::string GetSubjectDisplayName(CERTCertificate* cert_handle);
 
-bool GetTimes(CERTCertificate* cert_handle,
-              base::Time* issued,
-              base::Time* expires);
-
 std::string GetTitle(CERTCertificate* cert_handle);
-std::string GetIssuerName(CERTCertificate* cert_handle);
-std::string GetSubjectName(CERTCertificate* cert_handle);
-
-typedef std::vector<Extension> Extensions;
-
-void GetExtensions(const std::string& critical_label,
-                   const std::string& non_critical_label,
-                   CERTCertificate* cert_handle,
-                   Extensions* extensions);
-
-// Hash a certificate using the given algorithm, return the result as a
-// colon-seperated hex string.
-std::string HashCertSHA256(CERTCertificate* cert_handle);
-std::string HashCertSHA1(CERTCertificate* cert_handle);
-
-std::string ProcessSecAlgorithmSignature(CERTCertificate* cert_handle);
-std::string ProcessSecAlgorithmSubjectPublicKey(CERTCertificate* cert_handle);
-std::string ProcessSecAlgorithmSignatureWrap(CERTCertificate* cert_handle);
-
-// Formats the public key from the X.509 SubjectPublicKeyInfo extracted from
-// |cert_handle| as a string for displaying.
-std::string ProcessSubjectPublicKeyInfo(CERTCertificate* cert_handle);
-
-std::string ProcessRawBitsSignatureWrap(CERTCertificate* cert_handle);
 
 }  // namespace x509_certificate_model
 
diff --git a/chrome/common/net/x509_certificate_model_nss_unittest.cc b/chrome/common/net/x509_certificate_model_nss_unittest.cc
index 6e9cfb2..5961d46 100644
--- a/chrome/common/net/x509_certificate_model_nss_unittest.cc
+++ b/chrome/common/net/x509_certificate_model_nss_unittest.cc
@@ -53,156 +53,6 @@
             x509_certificate_model::GetTitle(no_cn_cert2.get()));
 }
 
-TEST_F(X509CertificateModelTest, GetExtensions) {
-  {
-    net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
-        net::GetTestCertsDirectory(), "root_ca_cert.pem"));
-    ASSERT_TRUE(cert.get());
-
-    x509_certificate_model::Extensions extensions;
-    x509_certificate_model::GetExtensions("critical", "notcrit", cert.get(),
-                                          &extensions);
-    ASSERT_EQ(3U, extensions.size());
-
-    EXPECT_EQ("Certificate Basic Constraints", extensions[0].name);
-    EXPECT_EQ(
-        "critical\nIs a Certification Authority\n"
-        "Maximum number of intermediate CAs: unlimited",
-        extensions[0].value);
-
-    EXPECT_EQ("Certificate Subject Key ID", extensions[1].name);
-    EXPECT_EQ(
-        "notcrit\nKey ID: 9B 26 0B 8A 98 A9 BB 1D B9 1F 1C E3 1A 40 33 ED\n8E "
-        "17 88 AB",
-        extensions[1].value);
-
-    EXPECT_EQ("Certificate Key Usage", extensions[2].name);
-    EXPECT_EQ("critical\nCertificate Signer\nCRL Signer", extensions[2].value);
-  }
-
-  {
-    net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
-        net::GetTestCertsDirectory(), "subjectAltName_sanity_check.pem"));
-    ASSERT_TRUE(cert.get());
-
-    x509_certificate_model::Extensions extensions;
-    x509_certificate_model::GetExtensions("critical", "notcrit", cert.get(),
-                                          &extensions);
-    ASSERT_EQ(2U, extensions.size());
-    EXPECT_EQ("Certificate Subject Alternative Name", extensions[1].name);
-    EXPECT_EQ(
-        "notcrit\nIP Address: 127.0.0.2\nIP Address: fe80::1\nDNS Name: "
-        "test.example\nEmail Address: test@test.example\nOID.1.2.3.4: 0C 09 69 "
-        "67 6E 6F 72 65 20 6D 65\nX.500 Name: CN = 127.0.0.3\n\n",
-        extensions[1].value);
-  }
-
-  {
-    net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
-        net::GetTestCertsDirectory(), "foaf.me.chromium-test-cert.der"));
-    ASSERT_TRUE(cert.get());
-
-    x509_certificate_model::Extensions extensions;
-    x509_certificate_model::GetExtensions("critical", "notcrit", cert.get(),
-                                          &extensions);
-    ASSERT_EQ(5U, extensions.size());
-    EXPECT_EQ("Netscape Certificate Comment", extensions[1].name);
-    EXPECT_EQ("notcrit\nOpenSSL Generated Certificate", extensions[1].value);
-  }
-
-  {
-    net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
-        net::GetTestCertsDirectory(), "2029_globalsign_com_cert.pem"));
-    ASSERT_TRUE(cert.get());
-
-    x509_certificate_model::Extensions extensions;
-    x509_certificate_model::GetExtensions("critical", "notcrit", cert.get(),
-                                          &extensions);
-    ASSERT_EQ(9U, extensions.size());
-
-    EXPECT_EQ("Certificate Subject Key ID", extensions[0].name);
-    EXPECT_EQ(
-        "notcrit\nKey ID: 59 BC D9 69 F7 B0 65 BB C8 34 C5 D2 C2 EF 17 78\nA6 "
-        "47 1E 8B",
-        extensions[0].value);
-
-    EXPECT_EQ("Certification Authority Key ID", extensions[1].name);
-    EXPECT_EQ(
-        "notcrit\nKey ID: 8A FC 14 1B 3D A3 59 67 A5 3B E1 73 92 A6 62 91\n7F "
-        "E4 78 30\n",
-        extensions[1].value);
-
-    EXPECT_EQ("Authority Information Access", extensions[2].name);
-    EXPECT_EQ(
-        "notcrit\nCA Issuers: "
-        "URI: http://secure.globalsign.net/cacert/SHA256extendval1.crt\n",
-        extensions[2].value);
-
-    EXPECT_EQ("CRL Distribution Points", extensions[3].name);
-    EXPECT_EQ("notcrit\nURI: http://crl.globalsign.net/SHA256ExtendVal1.crl\n",
-              extensions[3].value);
-
-    EXPECT_EQ("Certificate Basic Constraints", extensions[4].name);
-    EXPECT_EQ("notcrit\nIs not a Certification Authority\n",
-              extensions[4].value);
-
-    EXPECT_EQ("Certificate Key Usage", extensions[5].name);
-    EXPECT_EQ(
-        "critical\nSigning\nNon-repudiation\nKey Encipherment\n"
-        "Data Encipherment",
-        extensions[5].value);
-
-    EXPECT_EQ("Extended Key Usage", extensions[6].name);
-    EXPECT_EQ(
-        "notcrit\nTLS WWW Server Authentication (OID.1.3.6.1.5.5.7.3.1)\n"
-        "TLS WWW Client Authentication (OID.1.3.6.1.5.5.7.3.2)\n",
-        extensions[6].value);
-
-    EXPECT_EQ("Certificate Policies", extensions[7].name);
-    EXPECT_EQ(
-        "notcrit\nOID.1.3.6.1.4.1.4146.1.1:\n"
-        "  Certification Practice Statement Pointer:"
-        "    http://www.globalsign.net/repository/\n",
-        extensions[7].value);
-
-    EXPECT_EQ("Netscape Certificate Type", extensions[8].name);
-    EXPECT_EQ("notcrit\nSSL Client Certificate\nSSL Server Certificate",
-              extensions[8].value);
-  }
-
-  {
-    net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
-        net::GetTestCertsDirectory(), "diginotar_public_ca_2025.pem"));
-    ASSERT_TRUE(cert.get());
-
-    x509_certificate_model::Extensions extensions;
-    x509_certificate_model::GetExtensions("critical", "notcrit", cert.get(),
-                                          &extensions);
-    ASSERT_EQ(7U, extensions.size());
-
-    EXPECT_EQ("Authority Information Access", extensions[0].name);
-    EXPECT_EQ(
-        "notcrit\nOCSP Responder: "
-        "URI: http://validation.diginotar.nl\n",
-        extensions[0].value);
-
-    EXPECT_EQ("Certificate Basic Constraints", extensions[2].name);
-    EXPECT_EQ(
-        "critical\nIs a Certification Authority\n"
-        "Maximum number of intermediate CAs: 0",
-        extensions[2].value);
-    EXPECT_EQ("Certificate Policies", extensions[3].name);
-    EXPECT_EQ(
-        "notcrit\nOID.2.16.528.1.1001.1.1.1.1.5.2.6.4:\n"
-        "  Certification Practice Statement Pointer:"
-        "    http://www.diginotar.nl/cps\n"
-        "  User Notice:\n"
-        "    Conditions, as mentioned on our website (www.diginotar.nl), are "
-        "applicable to all our products and services.\n",
-        extensions[3].value);
-  }
-}
-
 TEST_F(X509CertificateModelTest, GetTypeCA) {
   net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
       net::GetTestCertsDirectory(), "root_ca_cert.pem"));
@@ -253,105 +103,3 @@
 
   EXPECT_EQ(net::SERVER_CERT, x509_certificate_model::GetType(cert.get()));
 }
-
-// An X.509 v1 certificate with the version field omitted should get
-// the default value v1.
-TEST_F(X509CertificateModelTest, GetVersionOmitted) {
-  net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
-      net::GetTestCertsDirectory(), "ndn.ca.crt"));
-  ASSERT_TRUE(cert.get());
-
-  EXPECT_EQ("1", x509_certificate_model::GetVersion(cert.get()));
-}
-
-TEST_F(X509CertificateModelTest, ProcessSecAlgorithms) {
-  {
-    net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
-        net::GetTestCertsDirectory(), "root_ca_cert.pem"));
-    ASSERT_TRUE(cert.get());
-
-    EXPECT_EQ("PKCS #1 SHA-256 With RSA Encryption",
-              x509_certificate_model::ProcessSecAlgorithmSignature(cert.get()));
-    EXPECT_EQ(
-        "PKCS #1 SHA-256 With RSA Encryption",
-        x509_certificate_model::ProcessSecAlgorithmSignatureWrap(cert.get()));
-    EXPECT_EQ("PKCS #1 RSA Encryption",
-              x509_certificate_model::ProcessSecAlgorithmSubjectPublicKey(
-                  cert.get()));
-  }
-  {
-    net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
-        net::GetTestCertsDirectory(), "weak_digest_md5_root.pem"));
-    ASSERT_TRUE(cert.get());
-
-    EXPECT_EQ("PKCS #1 MD5 With RSA Encryption",
-              x509_certificate_model::ProcessSecAlgorithmSignature(cert.get()));
-    EXPECT_EQ(
-        "PKCS #1 MD5 With RSA Encryption",
-        x509_certificate_model::ProcessSecAlgorithmSignatureWrap(cert.get()));
-    EXPECT_EQ("PKCS #1 RSA Encryption",
-              x509_certificate_model::ProcessSecAlgorithmSubjectPublicKey(
-                  cert.get()));
-  }
-}
-
-TEST_F(X509CertificateModelTest, ProcessSubjectPublicKeyInfo) {
-  {
-    net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
-        net::GetTestCertsDirectory(), "root_ca_cert.pem"));
-    ASSERT_TRUE(cert.get());
-
-    EXPECT_EQ(
-        "Modulus (2048 bits):\n"
-        "  C6 81 1F 92 73 B6 58 85 D9 8D AC B7 20 FD C7 BF\n"
-        "40 B2 EA FA E5 0B 52 01 8F 9A C1 EB 7A 80 C1 F3\n"
-        "89 A4 3E D5 1B 61 CC B5 CF 80 B1 1A DB BB 25 E0\n"
-        "18 BF 92 69 26 50 CD E7 3F FF 0D 3C B4 1F 14 12\n"
-        "AB 67 37 DE 07 03 6C 12 74 82 36 AC C3 D4 D3 64\n"
-        "9F 91 ED 5B F6 A9 7A A4 9C 98 E8 65 6C 94 E1 CB\n"
-        "55 73 AE F8 1D 50 B0 78 E5 74 FF B1 37 2C CB 19\n"
-        "3D A4 8C E7 76 4E 86 5C 3F DF B3 ED 45 23 4F 54\n"
-        "9B 33 C6 89 5E 13 1D DD 7D 59 A5 07 34 28 86 27\n"
-        "1F FA 9E 53 4F 2A B6 42 AD 37 12 62 F5 72 36 B6\n"
-        "02 12 40 44 FE C7 9E 95 89 43 51 5E B4 6E C7 67\n"
-        "80 58 43 BE CC 07 28 BD 59 FF 1C 4C 8D 90 42 F4\n"
-        "CF FD 54 00 4F 48 72 2B E1 67 3C 84 17 68 95 BF\n"
-        "CA 07 7B DF 86 9D 56 E3 32 E3 70 87 B7 F8 3A F7\n"
-        "E3 6E 65 14 7C BB 76 B7 17 F1 42 8C 6F 2A 34 64\n"
-        "10 35 14 8C 85 F6 57 BF F3 5C 55 9D AD 03 10 F3\n"
-        "\n"
-        "  Public Exponent (24 bits):\n"
-        "  01 00 01",
-        x509_certificate_model::ProcessSubjectPublicKeyInfo(cert.get()));
-  }
-  {
-    net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
-        net::GetTestCertsDirectory(), "prime256v1-ecdsa-intermediate.pem"));
-    ASSERT_TRUE(cert.get());
-
-    EXPECT_EQ(
-        "04 D5 C1 4A 32 95 95 C5 88 FA 01 FA C5 9E DC E2\n"
-        "99 62 EB 13 E5 35 42 B3 7A FC 46 C0 FA 29 12 C8\n"
-        "2D EA 30 0F D2 9A 47 97 2C 7E 89 E6 EF 49 55 06\n"
-        "C9 37 C7 99 56 16 B2 2B C9 7C 69 8E 10 7A DD 1F\n"
-        "42",
-        x509_certificate_model::ProcessSubjectPublicKeyInfo(cert.get()));
-  }
-}
-
-TEST_F(X509CertificateModelTest, ProcessRawBitsSignatureWrap) {
-  net::ScopedCERTCertificate cert(net::ImportCERTCertificateFromFile(
-      net::GetTestCertsDirectory(), "google.single.pem"));
-  ASSERT_TRUE(cert.get());
-
-  EXPECT_EQ(
-      "9F 43 CF 5B C4 50 29 B1 BF E2 B0 9A FF 6A 21 1D\n"
-      "2D 12 C3 2C 4E 5A F9 12 E2 CE B9 82 52 2D E7 1D\n"
-      "7E 1A 76 96 90 79 D1 24 52 38 79 BB 63 8D 80 97\n"
-      "7C 23 20 0F 91 4D 16 B9 EA EE F4 6D 89 CA C6 BD\n"
-      "CC 24 68 D6 43 5B CE 2A 58 BF 3C 18 E0 E0 3C 62\n"
-      "CF 96 02 2D 28 47 50 34 E1 27 BA CF 99 D1 50 FF\n"
-      "29 25 C0 36 36 15 33 52 70 BE 31 8F 9F E8 7F E7\n"
-      "11 0C 8D BF 84 A0 42 1A 80 89 B0 31 58 41 07 5F",
-      x509_certificate_model::ProcessRawBitsSignatureWrap(cert.get()));
-}
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index b34cac3..7b836b2f 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1185,6 +1185,7 @@
       "//chrome/browser/devtools",
       "//chrome/browser/devtools:test_support",
       "//chrome/browser/dips:browser_tests",
+      "//chrome/browser/favicon",
       "//chrome/browser/first_party_sets",
       "//chrome/browser/image_decoder:browser_tests",
       "//chrome/browser/media/router:media_router_feature",
@@ -5532,6 +5533,7 @@
     "//chrome/browser/commerce/shopping_list:unit_tests",
     "//chrome/browser/devtools",
     "//chrome/browser/dips:unit_tests",
+    "//chrome/browser/favicon",
     "//chrome/browser/feature_guide/notifications:unit_tests",
     "//chrome/browser/first_party_sets",
     "//chrome/browser/media/router",
@@ -9708,7 +9710,10 @@
       "../browser/sync/test/integration/sync_test_utils_android.h",
     ]
   }
-  public_deps = [ "//chrome/browser" ]
+  public_deps = [
+    "//chrome/browser",
+    "//chrome/browser/favicon",
+  ]
   deps = [
     ":test_support",
     "//base",
diff --git a/chrome/test/data/extensions/api_test/favicon/permission_missing/test.js b/chrome/test/data/extensions/api_test/favicon/permission_missing/test.js
index a3a06d7..0381dd9 100644
--- a/chrome/test/data/extensions/api_test/favicon/permission_missing/test.js
+++ b/chrome/test/data/extensions/api_test/favicon/permission_missing/test.js
@@ -9,7 +9,7 @@
     const id = chrome.runtime.id;
     const pageUrl =
         `http://www.example.com:${port}extensions/favicon/test_file.html`;
-    const url = `chrome-extension://${id}/_favicon/?page_url=${pageUrl}`;
+    const url = `chrome-extension://${id}/_favicon/?pageUrl=${pageUrl}`;
     fetch(url).then(() => chrome.test.fail()).catch(error => {
       chrome.test.assertEq('Failed to fetch', error.message);
       chrome.test.succeed();
diff --git a/chrome/test/data/webui/certificate_viewer_dialog_browsertest.js b/chrome/test/data/webui/certificate_viewer_dialog_browsertest.js
index 025f161..f22b6f8b 100644
--- a/chrome/test/data/webui/certificate_viewer_dialog_browsertest.js
+++ b/chrome/test/data/webui/certificate_viewer_dialog_browsertest.js
@@ -31,10 +31,18 @@
    * Show the certificate viewer dialog.
    */
   testGenPreamble: function() {
-    GEN('ShowCertificateViewer();');
+    GEN('ShowCertificateViewerGoogleCert();');
   },
 };
 
+var CertificateViewerUIInvalidCertTest = class extends CertificateViewerUITest {
+  get testGenPreamble() {
+    return () => {
+      GEN('ShowCertificateViewerInvalidCert();');
+    };
+  }
+};
+
 // Helper for loading the Mocha test file as a JS module. Not using
 // test_loader.html, as the test code needs to be loaded in the context of the
 // dialog triggered with the ShowCertificateViewer() C++ call above.
@@ -80,3 +88,9 @@
     mocha.grep('Details').run();
   });
 });
+
+TEST_F('CertificateViewerUIInvalidCertTest', 'InvalidCert', function() {
+  loadTestModule().then(() => {
+    mocha.grep('InvalidCert').run();
+  });
+});
diff --git a/chrome/test/data/webui/certificate_viewer_dialog_test.js b/chrome/test/data/webui/certificate_viewer_dialog_test.js
index 533d102..772fa6a 100644
--- a/chrome/test/data/webui/certificate_viewer_dialog_test.js
+++ b/chrome/test/data/webui/certificate_viewer_dialog_test.js
@@ -31,6 +31,9 @@
 
   // Tests for the correct common name in the test certificate.
   test('CommonName', function() {
+    assertTrue(document.querySelector('#general-error').hidden);
+    assertFalse(document.querySelector('#general-fields').hidden);
+
     assertEquals(
         'www.google.com', document.querySelector('#issued-cn').textContent);
   });
@@ -68,4 +71,16 @@
     certFields.selectedItem = certFields.items[0];
     assertEquals('', certFieldVal.textContent);
   });
+
+  test('InvalidCert', async function() {
+    // Error should be shown instead of cert fields.
+    assertFalse(document.querySelector('#general-error').hidden);
+    assertTrue(document.querySelector('#general-fields').hidden);
+
+    // Cert hash should still be shown.
+    assertEquals(
+        '78 71 88 FF A5 CC A4 82 12 ED 29 1E 62 CB 03 E1\n' +
+            '1C 1F 82 79 DF 07 FE B1 D2 B0 E0 2E 0E 4A A9 E4',
+        document.querySelector('#sha256').textContent);
+  });
 });
diff --git a/chrome/test/data/webui/certificate_viewer_ui_test-inl.h b/chrome/test/data/webui/certificate_viewer_ui_test-inl.h
index 37c9442..c01cef10 100644
--- a/chrome/test/data/webui/certificate_viewer_ui_test-inl.h
+++ b/chrome/test/data/webui/certificate_viewer_ui_test-inl.h
@@ -18,7 +18,7 @@
 #include "content/public/browser/web_ui.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
-#include "net/cert/x509_util_nss.h"
+#include "net/cert/x509_util.h"
 #include "net/test/test_certificate_data.h"
 
 // Test framework for
@@ -29,22 +29,38 @@
   ~CertificateViewerUITest() override;
 
  protected:
-  void ShowCertificateViewer();
+  void ShowCertificateViewerGoogleCert();
+  void ShowCertificateViewerInvalidCert();
+  void ShowCertificateViewer(std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs);
 };
 
-void CertificateViewerUITest::ShowCertificateViewer() {
-  net::ScopedCERTCertificate google_cert(
-      net::x509_util::CreateCERTCertificateFromBytes(google_der,
-                                                     sizeof(google_der)));
-  ASSERT_TRUE(google_cert);
-  net::ScopedCERTCertificateList certs;
-  certs.push_back(net::x509_util::DupCERTCertificate(google_cert.get()));
+void CertificateViewerUITest::ShowCertificateViewerGoogleCert() {
+  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs;
+  certs.push_back(
+      net::x509_util::CreateCryptoBuffer(base::make_span(google_der)));
+  ASSERT_TRUE(certs.back());
 
+  ShowCertificateViewer(std::move(certs));
+}
+
+void CertificateViewerUITest::ShowCertificateViewerInvalidCert() {
+  const uint8_t kInvalid[] = {42, 42, 42, 42, 42};
+  std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs;
+  certs.push_back(
+      net::x509_util::CreateCryptoBuffer(base::make_span(kInvalid)));
+  ASSERT_TRUE(certs.back());
+
+  ShowCertificateViewer(std::move(certs));
+}
+
+void CertificateViewerUITest::ShowCertificateViewer(
+    std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certs) {
   ASSERT_TRUE(browser());
   ASSERT_TRUE(browser()->window());
 
   CertificateViewerDialog* dialog = CertificateViewerDialog::ShowConstrained(
-      std::move(certs), browser()->tab_strip_model()->GetActiveWebContents(),
+      std::move(certs), /*cert_nicknames=*/{},
+      browser()->tab_strip_model()->GetActiveWebContents(),
       browser()->window()->GetNativeWindow());
   content::WebContents* webui_webcontents = dialog->webui_->GetWebContents();
   EXPECT_TRUE(content::WaitForLoadStop(webui_webcontents));
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
index 20806607..f298064 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
@@ -99,6 +99,12 @@
     // Verify the user email label is in the page.
     assertEquals('Email', getElementContent('#userEmailLabel'));
 
+    // Verify the share diagnostic data label is in the page.
+    assertTrue(page.i18nExists('shareDiagnosticDataLabel'));
+    assertEquals(
+        'Share diagnostic data',
+        getElementContent('#shareDiagnosticDataLabel'));
+
     // Screenshot elements.
     assertTrue(!!getElement('#screenshotCheckbox'));
     assertEquals('Screenshot', getElementContent('#screenshotCheckLabel'));
diff --git a/chrome/test/data/webui/extensions/url_util_test.ts b/chrome/test/data/webui/extensions/url_util_test.ts
index c8ad789..4ec4e1e 100644
--- a/chrome/test/data/webui/extensions/url_util_test.ts
+++ b/chrome/test/data/webui/extensions/url_util_test.ts
@@ -10,10 +10,10 @@
 suite('UrlUtilTest', function() {
   function getExpectedImageSet(url: string): string {
     return '-webkit-image-set(' +
-        'url("chrome://favicon2/?size=20&scale_factor=1x&page_url=' +
-        encodeURIComponent(url) + '&allow_google_server_fallback=0") 1x, ' +
-        'url("chrome://favicon2/?size=20&scale_factor=2x&page_url=' +
-        encodeURIComponent(url) + '&allow_google_server_fallback=0") 2x)';
+        'url("chrome://favicon2/?size=20&scaleFactor=1x&pageUrl=' +
+        encodeURIComponent(url) + '&allowGoogleServerFallback=0") 1x, ' +
+        'url("chrome://favicon2/?size=20&scaleFactor=2x&pageUrl=' +
+        encodeURIComponent(url) + '&allowGoogleServerFallback=0") 2x)';
   }
 
   test('favicon for normal URL', function() {
diff --git a/chrome/test/data/webui/js/icon_test.ts b/chrome/test/data/webui/js/icon_test.ts
index b2587ee..2dcd9e1 100644
--- a/chrome/test/data/webui/js/icon_test.ts
+++ b/chrome/test/data/webui/js/icon_test.ts
@@ -12,13 +12,13 @@
 
     function getExpectedImageSet(size: number): string {
       const expectedDesktop = '-webkit-image-set(' +
-          `url("chrome://favicon2/?size=${size}&scale_factor=1x&page_url=` +
-          encodeURIComponent(url) + '&allow_google_server_fallback=0") 1x, ' +
-          `url("chrome://favicon2/?size=${size}&scale_factor=2x&page_url=` +
-          encodeURIComponent(url) + '&allow_google_server_fallback=0") 2x)';
+          `url("chrome://favicon2/?size=${size}&scaleFactor=1x&pageUrl=` +
+          encodeURIComponent(url) + '&allowGoogleServerFallback=0") 1x, ' +
+          `url("chrome://favicon2/?size=${size}&scaleFactor=2x&pageUrl=` +
+          encodeURIComponent(url) + '&allowGoogleServerFallback=0") 2x)';
       const expectedOther = '-webkit-image-set(' +
-          `url("chrome://favicon2/?size=${size}&scale_factor=1x&page_url=` +
-          encodeURIComponent(url) + '&allow_google_server_fallback=0") ' +
+          `url("chrome://favicon2/?size=${size}&scaleFactor=1x&pageUrl=` +
+          encodeURIComponent(url) + '&allowGoogleServerFallback=0") ' +
           window.devicePixelRatio + 'x)';
 
       const isDesktop = isMac || isChromeOS || isWindows || isLinux || isLacros;
@@ -33,12 +33,12 @@
   test('GetFavicon', function() {
     const url = 'http://foo.com/foo.ico';
     const expectedDesktop = '-webkit-image-set(' +
-        'url("chrome://favicon2/?size=16&scale_factor=1x&icon_url=' +
+        'url("chrome://favicon2/?size=16&scaleFactor=1x&iconUrl=' +
         encodeURIComponent('http://foo.com/foo.ico') + '") 1x, ' +
-        'url("chrome://favicon2/?size=16&scale_factor=2x&icon_url=' +
+        'url("chrome://favicon2/?size=16&scaleFactor=2x&iconUrl=' +
         encodeURIComponent('http://foo.com/foo.ico') + '") 2x)';
     const expectedOther = '-webkit-image-set(' +
-        'url("chrome://favicon2/?size=16&scale_factor=1x&icon_url=' +
+        'url("chrome://favicon2/?size=16&scaleFactor=1x&iconUrl=' +
         encodeURIComponent('http://foo.com/foo.ico') + '") ' +
         window.devicePixelRatio + 'x)';
 
diff --git a/chrome/test/data/webui/new_tab_page/modules/cart/discount_consent_card_test.ts b/chrome/test/data/webui/new_tab_page/modules/cart/discount_consent_card_test.ts
index 4134427..64f0e458 100644
--- a/chrome/test/data/webui/new_tab_page/modules/cart/discount_consent_card_test.ts
+++ b/chrome/test/data/webui/new_tab_page/modules/cart/discount_consent_card_test.ts
@@ -162,8 +162,8 @@
       });
 
   function buildFaviconUrl(merchantUrl: string): string {
-    return 'chrome://favicon2/?size=20&scale_factor=1x&show_fallback_monogram=&page_url=' +
-        encodeURIComponent(merchantUrl);
+    const query = '?size=20&scaleFactor=1x&showFallbackMonogram=&pageUrl=';
+    return `chrome://favicon2/${query}${encodeURIComponent(merchantUrl)}`;
   }
 
   test('Verify favicon is loaded', async () => {
diff --git a/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js b/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js
index 0b3c2c3b..3e1d73a 100644
--- a/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js
@@ -749,6 +749,57 @@
         `Diagnostics should be focused for settingId=${diagnosticsId}.`);
   });
 
+  test('FirmwareUpdatesBadge No Updates', async function() {
+    loadTimeData.overrideValues({isFirmwareUpdaterAppEnabled: true});
+
+    aboutBrowserProxy.setFirmwareUpdatesCount(0);
+    await initNewPage();
+    flush();
+    await aboutBrowserProxy.whenCalled('getFirmwareUpdateCount');
+
+    assertTrue(!!page.$.firmwareUpdateBadge);
+    assertTrue(!!page.$.firmwareUpdateBadgeSeparator);
+
+    assertTrue(page.$.firmwareUpdateBadge.hidden);
+    assertTrue(page.$.firmwareUpdateBadgeSeparator.hidden);
+  });
+
+  test('FirmwareUpdatesBadge N Updates', async function() {
+    loadTimeData.overrideValues({isFirmwareUpdaterAppEnabled: true});
+
+    for (let i = 1; i < 10; i++) {
+      aboutBrowserProxy.setFirmwareUpdatesCount(i);
+      await initNewPage();
+      flush();
+      await aboutBrowserProxy.whenCalled('getFirmwareUpdateCount');
+
+      assertTrue(!!page.$.firmwareUpdateBadge);
+      assertTrue(!!page.$.firmwareUpdateBadgeSeparator);
+
+      assertFalse(page.$.firmwareUpdateBadge.hidden);
+      assertEquals('os-settings:counter-' + i, page.$.firmwareUpdateBadge.icon);
+
+      assertFalse(page.$.firmwareUpdateBadgeSeparator.hidden);
+    }
+  });
+
+  test('FirmwareUpdatesBadge 10 Updates', async function() {
+    loadTimeData.overrideValues({isFirmwareUpdaterAppEnabled: true});
+
+    aboutBrowserProxy.setFirmwareUpdatesCount(10);
+    await initNewPage();
+    flush();
+    await aboutBrowserProxy.whenCalled('getFirmwareUpdateCount');
+
+    assertTrue(!!page.$.firmwareUpdateBadge);
+    assertTrue(!!page.$.firmwareUpdateBadgeSeparator);
+
+    assertFalse(page.$.firmwareUpdateBadge.hidden);
+    assertEquals('os-settings:counter-9', page.$.firmwareUpdateBadge.icon);
+
+    assertFalse(page.$.firmwareUpdateBadgeSeparator.hidden);
+  });
+
   test('LaunchFirmwareUpdates', async function() {
     loadTimeData.overrideValues({
       isDeepLinkingEnabled: true,
diff --git a/chrome/test/data/webui/settings/chromeos/test_about_page_browser_proxy_chromeos.js b/chrome/test/data/webui/settings/chromeos/test_about_page_browser_proxy_chromeos.js
index 53269ca..f7cb90f6 100644
--- a/chrome/test/data/webui/settings/chromeos/test_about_page_browser_proxy_chromeos.js
+++ b/chrome/test/data/webui/settings/chromeos/test_about_page_browser_proxy_chromeos.js
@@ -27,6 +27,7 @@
       'refreshTPMFirmwareUpdateStatus',
       'requestUpdate',
       'setChannel',
+      'getFirmwareUpdateCount',
       'openFirmwareUpdatesPage',
       'isManagedAutoUpdateEnabled',
       'isConsumerAutoUpdateEnabled',
@@ -73,6 +74,9 @@
 
     /** @private {!boolean} */
     this.consumerAutoUpdateEnabled_ = true;
+
+    /** @private {number} */
+    this.firmwareUpdateCount_ = 0;
   }
 
   /** @param {!UpdateStatus} updateStatus */
@@ -244,6 +248,17 @@
   }
 
   /** @override */
+  getFirmwareUpdateCount() {
+    this.methodCalled('getFirmwareUpdateCount');
+    return Promise.resolve(this.firmwareUpdateCount_);
+  }
+
+  /** @param {number} firmwareUpdatesCount */
+  setFirmwareUpdatesCount(firmwareUpdatesCount) {
+    this.firmwareUpdateCount_ = firmwareUpdatesCount;
+  }
+
+  /** @override */
   isManagedAutoUpdateEnabled() {
     this.methodCalled('isManagedAutoUpdateEnabled');
     return Promise.resolve(this.managedAutoUpdateEnabled_);
diff --git a/chrome/test/data/webui/settings/site_favicon_test.ts b/chrome/test/data/webui/settings/site_favicon_test.ts
index 303d642b..01bf847f 100644
--- a/chrome/test/data/webui/settings/site_favicon_test.ts
+++ b/chrome/test/data/webui/settings/site_favicon_test.ts
@@ -23,10 +23,10 @@
 
   function formExpected(url: string): string {
     return '-webkit-image-set(' +
-        'url("chrome://favicon2/?size=16&scale_factor=1x&page_url=' +
-        encodeURIComponent(url) + '&allow_google_server_fallback=0") 1x, ' +
-        'url("chrome://favicon2/?size=16&scale_factor=2x&page_url=' +
-        encodeURIComponent(url) + '&allow_google_server_fallback=0") 2x)';
+        'url("chrome://favicon2/?size=16&scaleFactor=1x&pageUrl=' +
+        encodeURIComponent(url) + '&allowGoogleServerFallback=0") 1x, ' +
+        'url("chrome://favicon2/?size=16&scaleFactor=2x&pageUrl=' +
+        encodeURIComponent(url) + '&allowGoogleServerFallback=0") 2x)';
   }
 
   test('normal URL', function() {
diff --git a/chrome/test/data/webui/usb_internals_test.js b/chrome/test/data/webui/usb_internals_test.js
index 7cc26cd8..fc6e90d 100644
--- a/chrome/test/data/webui/usb_internals_test.js
+++ b/chrome/test/data/webui/usb_internals_test.js
@@ -3,12 +3,12 @@
 // found in the LICENSE file.
 
 import 'chrome://usb-internals/app.js';
-
 import 'chrome://test/mojo_webui_test_support.js';
 
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
 import {String16} from 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-webui.js';
 import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.js';
+import {eventToPromise} from 'chrome://test/test_util.js';
 import {UsbControlTransferParams, UsbControlTransferRecipient, UsbControlTransferType, UsbDeviceCallbackRouter, UsbDeviceRemote, UsbOpenDeviceError, UsbTransferStatus} from 'chrome://usb-internals/usb_device.mojom-webui.js';
 import {UsbInternalsPageHandler, UsbInternalsPageHandlerReceiver, UsbInternalsPageHandlerRemote} from 'chrome://usb-internals/usb_internals.mojom-webui.js';
 import {UsbDeviceManagerReceiver, UsbDeviceManagerRemote} from 'chrome://usb-internals/usb_manager.mojom-webui.js';
@@ -235,7 +235,8 @@
 const setupResolver = new PromiseResolver();
 const deviceManagerGetDevicesResolver = new PromiseResolver();
 const deviceTabInitializedResolver = new PromiseResolver();
-let deviceDescriptorRenderResolver = new PromiseResolver();
+let deviceDescriptorRenderPromise =
+    eventToPromise('device-descriptor-complete-for-test', document.body);
 let pageHandler = null;
 
 window.deviceListCompleteFn = () => {
@@ -246,10 +247,6 @@
   deviceTabInitializedResolver.resolve();
 };
 
-window.deviceDescriptorCompleteFn = () => {
-  deviceDescriptorRenderResolver.resolve();
-};
-
 window.setupFn = () => {
   const pageHandlerInterceptor =
       new MojoInterfaceInterceptor(UsbInternalsPageHandler.$interfaceName);
@@ -369,7 +366,7 @@
     const deviceTab = app.shadowRoot.querySelectorAll('div[slot=\'panel\']')[2];
     deviceTab.querySelector('.device-descriptor-button').click();
 
-    await deviceDescriptorRenderResolver.promise;
+    await deviceDescriptorRenderPromise;
     const panel = deviceTab.querySelector('.device-descriptor-panel');
     assertEquals(1, panel.querySelectorAll('descriptorpanel').length);
     assertEquals(0, panel.querySelectorAll('error').length);
@@ -434,10 +431,11 @@
     const deviceTab = app.shadowRoot.querySelectorAll('div[slot=\'panel\']')[3];
 
     await deviceTabInitializedResolver.promise;
-    deviceDescriptorRenderResolver = new PromiseResolver();
+    deviceDescriptorRenderPromise =
+        eventToPromise('device-descriptor-complete-for-test', document.body);
     deviceTab.querySelector('.device-descriptor-button').click();
 
-    await deviceDescriptorRenderResolver.promise;
+    await deviceDescriptorRenderPromise;
     const panel = deviceTab.querySelector('.device-descriptor-panel');
 
     assertEquals(1, panel.querySelectorAll('descriptorpanel').length);
diff --git a/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.cpp b/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.cpp
index 4f43b6d..a19fb61 100644
--- a/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.cpp
+++ b/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.cpp
@@ -41,1062 +41,9 @@
 #include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h"
 
 #include <certdb.h>
-#include <keyhi.h>
-#include <prprf.h>
-#include <stddef.h>
-#include <unicode/uidna.h>
-
-#include "base/i18n/number_formatting.h"
-#include "base/lazy_instance.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/common/net/x509_certificate_model_nss.h"
-#include "chrome/grit/generated_resources.h"
-#include "components/strings/grit/components_strings.h"
-#include "crypto/scoped_nss_types.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace {
-
-std::string BMPtoUTF8(PRArenaPool* arena, unsigned char* data,
-                      unsigned int len) {
-  if (len % 2 != 0)
-    return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
-
-  unsigned int utf8_val_len = len * 3 + 1;
-  std::vector<unsigned char> utf8_val(utf8_val_len);
-  if (!PORT_UCS2_UTF8Conversion(PR_FALSE, data, len,
-                                &utf8_val.front(), utf8_val_len, &utf8_val_len))
-    return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
-  return std::string(reinterpret_cast<char*>(&utf8_val.front()), utf8_val_len);
-}
-
-SECOidTag RegisterDynamicOid(const char* oid_string) {
-  SECOidTag rv = SEC_OID_UNKNOWN;
-  unsigned char buffer[1024];
-  SECOidData od;
-  od.oid.type = siDEROID;
-  od.oid.data = buffer;
-  od.oid.len = sizeof(buffer);
-
-  if (SEC_StringToOID(NULL, &od.oid, oid_string, 0) == SECSuccess) {
-    od.offset = SEC_OID_UNKNOWN;
-    od.mechanism = CKM_INVALID_MECHANISM;
-    od.supportedExtension = INVALID_CERT_EXTENSION;
-    od.desc = oid_string;
-
-    rv = SECOID_AddEntry(&od);
-  }
-  DCHECK_NE(rv, SEC_OID_UNKNOWN) << oid_string;
-  return rv;
-}
-
-// Format a SECItem as a space separated string, with 16 bytes on each line.
-std::string ProcessRawBytes(SECItem* data) {
-  return x509_certificate_model::ProcessRawBytes(data->data, data->len);
-}
-
-SECOidTag ms_cert_ext_certtype = SEC_OID_UNKNOWN;
-SECOidTag ms_certsrv_ca_version = SEC_OID_UNKNOWN;
-SECOidTag ms_nt_principal_name = SEC_OID_UNKNOWN;
-SECOidTag ms_ntds_replication = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_individual_code_signing = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_commercial_code_signing = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_trust_list_signing = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_time_stamping = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_server_gated_crypto = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_encrypting_file_system = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_file_recovery = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_windows_hardware_driver_verification = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_qualified_subordination = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_key_recovery = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_document_signing = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_lifetime_signing = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_smart_card_logon = SEC_OID_UNKNOWN;
-SECOidTag eku_ms_key_recovery_agent = SEC_OID_UNKNOWN;
-SECOidTag eku_netscape_international_step_up = SEC_OID_UNKNOWN;
-
-class DynamicOidRegisterer {
- public:
-  DynamicOidRegisterer() {
-    ms_cert_ext_certtype = RegisterDynamicOid("1.3.6.1.4.1.311.20.2");
-    ms_certsrv_ca_version = RegisterDynamicOid("1.3.6.1.4.1.311.21.1");
-    ms_nt_principal_name = RegisterDynamicOid("1.3.6.1.4.1.311.20.2.3");
-    ms_ntds_replication = RegisterDynamicOid("1.3.6.1.4.1.311.25.1");
-
-    eku_ms_individual_code_signing = RegisterDynamicOid("1.3.6.1.4.1.311.2.1.21");
-    eku_ms_commercial_code_signing = RegisterDynamicOid("1.3.6.1.4.1.311.2.1.22");
-    eku_ms_trust_list_signing = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.1");
-    eku_ms_time_stamping = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.2");
-    eku_ms_server_gated_crypto = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.3");
-    eku_ms_encrypting_file_system = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.4");
-    eku_ms_file_recovery = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.4.1");
-    eku_ms_windows_hardware_driver_verification = RegisterDynamicOid(
-        "1.3.6.1.4.1.311.10.3.5");
-    eku_ms_qualified_subordination = RegisterDynamicOid(
-        "1.3.6.1.4.1.311.10.3.10");
-    eku_ms_key_recovery = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.11");
-    eku_ms_document_signing = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.12");
-    eku_ms_lifetime_signing = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.13");
-    eku_ms_smart_card_logon = RegisterDynamicOid("1.3.6.1.4.1.311.20.2.2");
-    eku_ms_key_recovery_agent = RegisterDynamicOid("1.3.6.1.4.1.311.21.6");
-    eku_netscape_international_step_up = RegisterDynamicOid(
-        "2.16.840.1.113730.4.1");
-  }
-};
-
-static base::LazyInstance<DynamicOidRegisterer>::Leaky
-    g_dynamic_oid_registerer = LAZY_INSTANCE_INITIALIZER;
-
-}  // namespace
 
 namespace mozilla_security_manager {
 
-std::string DumpOidString(SECItem* oid) {
-  char* pr_string = CERT_GetOidString(oid);
-  if (pr_string) {
-    std::string rv = pr_string;
-    PR_smprintf_free(pr_string);
-    return rv;
-  }
-
-  return ProcessRawBytes(oid);
-}
-
-std::string GetOIDText(SECItem* oid) {
-  g_dynamic_oid_registerer.Get();
-
-  int string_id;
-  SECOidTag oid_tag = SECOID_FindOIDTag(oid);
-  switch (oid_tag) {
-    // Distinguished Name fields:
-    case SEC_OID_AVA_COMMON_NAME:
-      string_id = IDS_CERT_OID_AVA_COMMON_NAME;
-      break;
-    case SEC_OID_AVA_STATE_OR_PROVINCE:
-      string_id = IDS_CERT_OID_AVA_STATE_OR_PROVINCE;
-      break;
-    case SEC_OID_AVA_ORGANIZATION_NAME:
-      string_id = IDS_CERT_OID_AVA_ORGANIZATION_NAME;
-      break;
-    case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
-      string_id = IDS_CERT_OID_AVA_ORGANIZATIONAL_UNIT_NAME;
-      break;
-    case SEC_OID_AVA_DN_QUALIFIER:
-      string_id = IDS_CERT_OID_AVA_DN_QUALIFIER;
-      break;
-    case SEC_OID_AVA_COUNTRY_NAME:
-      string_id = IDS_CERT_OID_AVA_COUNTRY_NAME;
-      break;
-    case SEC_OID_AVA_SERIAL_NUMBER:
-      string_id = IDS_CERT_OID_AVA_SERIAL_NUMBER;
-      break;
-    case SEC_OID_AVA_LOCALITY:
-      string_id = IDS_CERT_OID_AVA_LOCALITY;
-      break;
-    case SEC_OID_AVA_DC:
-      string_id = IDS_CERT_OID_AVA_DC;
-      break;
-    case SEC_OID_RFC1274_MAIL:
-      string_id = IDS_CERT_OID_RFC1274_MAIL;
-      break;
-    case SEC_OID_RFC1274_UID:
-      string_id = IDS_CERT_OID_RFC1274_UID;
-      break;
-    case SEC_OID_PKCS9_EMAIL_ADDRESS:
-      string_id = IDS_CERT_OID_PKCS9_EMAIL_ADDRESS;
-      break;
-
-    // Extended Validation (EV) name fields:
-    case SEC_OID_BUSINESS_CATEGORY:
-      string_id = IDS_CERT_OID_BUSINESS_CATEGORY;
-      break;
-    case SEC_OID_EV_INCORPORATION_LOCALITY:
-      string_id = IDS_CERT_OID_EV_INCORPORATION_LOCALITY;
-      break;
-    case SEC_OID_EV_INCORPORATION_STATE:
-      string_id = IDS_CERT_OID_EV_INCORPORATION_STATE;
-      break;
-    case SEC_OID_EV_INCORPORATION_COUNTRY:
-      string_id = IDS_CERT_OID_EV_INCORPORATION_COUNTRY;
-      break;
-    case SEC_OID_AVA_STREET_ADDRESS:
-      string_id = IDS_CERT_OID_AVA_STREET_ADDRESS;
-      break;
-    case SEC_OID_AVA_POSTAL_CODE:
-      string_id = IDS_CERT_OID_AVA_POSTAL_CODE;
-      break;
-
-    // Algorithm fields:
-    case SEC_OID_PKCS1_RSA_ENCRYPTION:
-      string_id = IDS_CERT_OID_PKCS1_RSA_ENCRYPTION;
-      break;
-    case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
-      string_id = IDS_CERT_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
-      break;
-    case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
-      string_id = IDS_CERT_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION;
-      break;
-    case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
-      string_id = IDS_CERT_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
-      break;
-    case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
-      string_id = IDS_CERT_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
-      break;
-    case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
-      string_id = IDS_CERT_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
-      break;
-    case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
-      string_id = IDS_CERT_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
-      break;
-    case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
-      string_id = IDS_CERT_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
-      break;
-    case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
-      string_id = IDS_CERT_OID_ANSIX962_ECDSA_SHA1_SIGNATURE;
-      break;
-    case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
-      string_id = IDS_CERT_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
-      break;
-    case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
-      string_id = IDS_CERT_OID_ANSIX962_ECDSA_SHA384_SIGNATURE;
-      break;
-    case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
-      string_id = IDS_CERT_OID_ANSIX962_ECDSA_SHA512_SIGNATURE;
-      break;
-    case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
-      string_id = IDS_CERT_OID_ANSIX962_EC_PUBLIC_KEY;
-      break;
-    case SEC_OID_SECG_EC_SECP256R1:
-      string_id = IDS_CERT_OID_SECG_EC_SECP256R1;
-      break;
-    case SEC_OID_SECG_EC_SECP384R1:
-      string_id = IDS_CERT_OID_SECG_EC_SECP384R1;
-      break;
-    case SEC_OID_SECG_EC_SECP521R1:
-      string_id = IDS_CERT_OID_SECG_EC_SECP521R1;
-      break;
-
-    // Extension fields (including details of extensions):
-    case SEC_OID_NS_CERT_EXT_CERT_TYPE:
-      string_id = IDS_CERT_EXT_NS_CERT_TYPE;
-      break;
-    case SEC_OID_NS_CERT_EXT_BASE_URL:
-      string_id = IDS_CERT_EXT_NS_CERT_BASE_URL;
-      break;
-    case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
-      string_id = IDS_CERT_EXT_NS_CERT_REVOCATION_URL;
-      break;
-    case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
-      string_id = IDS_CERT_EXT_NS_CA_REVOCATION_URL;
-      break;
-    case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
-      string_id = IDS_CERT_EXT_NS_CERT_RENEWAL_URL;
-      break;
-    case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
-      string_id = IDS_CERT_EXT_NS_CA_POLICY_URL;
-      break;
-    case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
-      string_id = IDS_CERT_EXT_NS_SSL_SERVER_NAME;
-      break;
-    case SEC_OID_NS_CERT_EXT_COMMENT:
-      string_id = IDS_CERT_EXT_NS_COMMENT;
-      break;
-    case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
-      string_id = IDS_CERT_EXT_NS_LOST_PASSWORD_URL;
-      break;
-    case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
-      string_id = IDS_CERT_EXT_NS_CERT_RENEWAL_TIME;
-      break;
-    case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
-      string_id = IDS_CERT_X509_SUBJECT_DIRECTORY_ATTR;
-      break;
-    case SEC_OID_X509_SUBJECT_KEY_ID:
-      string_id = IDS_CERT_X509_SUBJECT_KEYID;
-      break;
-    case SEC_OID_X509_KEY_USAGE:
-      string_id = IDS_CERT_X509_KEY_USAGE;
-      break;
-    case SEC_OID_X509_SUBJECT_ALT_NAME:
-      string_id = IDS_CERT_X509_SUBJECT_ALT_NAME;
-      break;
-    case SEC_OID_X509_ISSUER_ALT_NAME:
-      string_id = IDS_CERT_X509_ISSUER_ALT_NAME;
-      break;
-    case SEC_OID_X509_BASIC_CONSTRAINTS:
-      string_id = IDS_CERT_X509_BASIC_CONSTRAINTS;
-      break;
-    case SEC_OID_X509_NAME_CONSTRAINTS:
-      string_id = IDS_CERT_X509_NAME_CONSTRAINTS;
-      break;
-    case SEC_OID_X509_CRL_DIST_POINTS:
-      string_id = IDS_CERT_X509_CRL_DIST_POINTS;
-      break;
-    case SEC_OID_X509_CERTIFICATE_POLICIES:
-      string_id = IDS_CERT_X509_CERT_POLICIES;
-      break;
-    case SEC_OID_X509_POLICY_MAPPINGS:
-      string_id = IDS_CERT_X509_POLICY_MAPPINGS;
-      break;
-    case SEC_OID_X509_POLICY_CONSTRAINTS:
-      string_id = IDS_CERT_X509_POLICY_CONSTRAINTS;
-      break;
-    case SEC_OID_X509_AUTH_KEY_ID:
-      string_id = IDS_CERT_X509_AUTH_KEYID;
-      break;
-    case SEC_OID_X509_EXT_KEY_USAGE:
-      string_id = IDS_CERT_X509_EXT_KEY_USAGE;
-      break;
-    case SEC_OID_X509_AUTH_INFO_ACCESS:
-      string_id = IDS_CERT_X509_AUTH_INFO_ACCESS;
-      break;
-    case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
-      string_id = IDS_CERT_PKIX_CPS_POINTER_QUALIFIER;
-      break;
-    case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
-      string_id = IDS_CERT_PKIX_USER_NOTICE_QUALIFIER;
-      break;
-
-    // Extended Key Usages:
-    case SEC_OID_EXT_KEY_USAGE_SERVER_AUTH:
-      string_id = IDS_CERT_EKU_TLS_WEB_SERVER_AUTHENTICATION;
-      break;
-    case SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH:
-      string_id = IDS_CERT_EKU_TLS_WEB_CLIENT_AUTHENTICATION;
-      break;
-    case SEC_OID_EXT_KEY_USAGE_CODE_SIGN:
-      string_id = IDS_CERT_EKU_CODE_SIGNING;
-      break;
-    case SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT:
-      string_id = IDS_CERT_EKU_EMAIL_PROTECTION;
-      break;
-    case SEC_OID_EXT_KEY_USAGE_TIME_STAMP:
-      string_id = IDS_CERT_EKU_TIME_STAMPING;
-      break;
-    case SEC_OID_OCSP_RESPONDER:
-      string_id = IDS_CERT_EKU_OCSP_SIGNING;
-      break;
-
-    // Explicitly handle UNKNOWN to avoid the conditional below.
-    case SEC_OID_UNKNOWN:
-      string_id = -1;
-      break;
-
-    // OIDs that are not directly registered with NSS, and thus cannot be
-    // used as part of a switch tag. While there is a potentially boundless
-    // set here, only list ones that either other platforms list or which
-    // might otherwise be encountered in the Web PKI or mainstream Enterprise
-    // deployments.
-    default:
-      if (oid_tag == ms_cert_ext_certtype)
-        string_id = IDS_CERT_EXT_MS_CERT_TYPE;
-      else if (oid_tag == ms_certsrv_ca_version)
-        string_id = IDS_CERT_EXT_MS_CA_VERSION;
-      else if (oid_tag == ms_nt_principal_name)
-        string_id = IDS_CERT_EXT_MS_NT_PRINCIPAL_NAME;
-      else if (oid_tag == ms_ntds_replication)
-        string_id = IDS_CERT_EXT_MS_NTDS_REPLICATION;
-      else if (oid_tag == eku_ms_individual_code_signing)
-        string_id = IDS_CERT_EKU_MS_INDIVIDUAL_CODE_SIGNING;
-      else if (oid_tag == eku_ms_commercial_code_signing)
-        string_id = IDS_CERT_EKU_MS_COMMERCIAL_CODE_SIGNING;
-      else if (oid_tag == eku_ms_trust_list_signing)
-        string_id = IDS_CERT_EKU_MS_TRUST_LIST_SIGNING;
-      else if (oid_tag == eku_ms_time_stamping)
-        string_id = IDS_CERT_EKU_MS_TIME_STAMPING;
-      else if (oid_tag == eku_ms_server_gated_crypto)
-        string_id = IDS_CERT_EKU_MS_SERVER_GATED_CRYPTO;
-      else if (oid_tag == eku_ms_encrypting_file_system)
-        string_id = IDS_CERT_EKU_MS_ENCRYPTING_FILE_SYSTEM;
-      else if (oid_tag == eku_ms_file_recovery)
-        string_id = IDS_CERT_EKU_MS_FILE_RECOVERY;
-      else if (oid_tag == eku_ms_windows_hardware_driver_verification)
-        string_id = IDS_CERT_EKU_MS_WINDOWS_HARDWARE_DRIVER_VERIFICATION;
-      else if (oid_tag == eku_ms_qualified_subordination)
-        string_id = IDS_CERT_EKU_MS_QUALIFIED_SUBORDINATION;
-      else if (oid_tag == eku_ms_key_recovery)
-        string_id = IDS_CERT_EKU_MS_KEY_RECOVERY;
-      else if (oid_tag == eku_ms_document_signing)
-        string_id = IDS_CERT_EKU_MS_DOCUMENT_SIGNING;
-      else if (oid_tag == eku_ms_lifetime_signing)
-        string_id = IDS_CERT_EKU_MS_LIFETIME_SIGNING;
-      else if (oid_tag == eku_ms_smart_card_logon)
-        string_id = IDS_CERT_EKU_MS_SMART_CARD_LOGON;
-      else if (oid_tag == eku_ms_key_recovery_agent)
-        string_id = IDS_CERT_EKU_MS_KEY_RECOVERY_AGENT;
-      else if (oid_tag == eku_netscape_international_step_up)
-        string_id = IDS_CERT_EKU_NETSCAPE_INTERNATIONAL_STEP_UP;
-      else
-        string_id = -1;
-      break;
-  }
-  if (string_id >= 0)
-    return l10n_util::GetStringUTF8(string_id);
-
-  return DumpOidString(oid);
-}
-
-// Get a display string from a Relative Distinguished Name.
-std::string ProcessRDN(CERTRDN* rdn) {
-  std::string rv;
-
-  CERTAVA** avas = rdn->avas;
-  for (size_t i = 0; avas[i] != NULL; ++i) {
-    rv += GetOIDText(&avas[i]->type);
-    SECItem* decode_item = CERT_DecodeAVAValue(&avas[i]->value);
-    if (decode_item) {
-      // TODO(mattm): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
-      rv += " = ";
-      std::string value(reinterpret_cast<char*>(decode_item->data),
-                        decode_item->len);
-      if (SECOID_FindOIDTag(&avas[i]->type) == SEC_OID_AVA_COMMON_NAME)
-        value = x509_certificate_model::ProcessIDN(value);
-      rv += value;
-      SECITEM_FreeItem(decode_item, PR_TRUE);
-    }
-    rv += '\n';
-  }
-
-  return rv;
-}
-
-std::string ProcessName(CERTName* name) {
-  std::string rv;
-  CERTRDN** last_rdn;
-
-  // Find last non-NULL rdn.
-  for (last_rdn = name->rdns; last_rdn[0]; last_rdn++) {}
-  last_rdn--;
-
-  for (CERTRDN** rdn = last_rdn; rdn >= name->rdns; rdn--)
-    rv += ProcessRDN(*rdn);
-  return rv;
-}
-
-std::string ProcessBasicConstraints(SECItem* extension_data) {
-  CERTBasicConstraints value;
-  value.pathLenConstraint = -1;
-  if (CERT_DecodeBasicConstraintValue(&value, extension_data) != SECSuccess)
-    return ProcessRawBytes(extension_data);
-
-  std::string rv;
-  if (value.isCA)
-    rv = l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_CA);
-  else
-    rv = l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_NOT_CA);
-  rv += '\n';
-  if (value.pathLenConstraint != -1) {
-    std::u16string depth;
-    if (value.pathLenConstraint == CERT_UNLIMITED_PATH_CONSTRAINT) {
-      depth = l10n_util::GetStringUTF16(
-          IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN_UNLIMITED);
-    } else {
-      depth = base::FormatNumber(value.pathLenConstraint);
-    }
-    rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN,
-                                    depth);
-  }
-  return rv;
-}
-
-std::string ProcessGeneralName(PRArenaPool* arena,
-                               CERTGeneralName* current) {
-  DCHECK(current);
-
-  std::string key;
-  std::string value;
-
-  switch (current->type) {
-    case certOtherName: {
-      key = GetOIDText(&current->name.OthName.oid);
-      // g_dynamic_oid_registerer.Get() will have been run by GetOIDText.
-      SECOidTag oid_tag = SECOID_FindOIDTag(&current->name.OthName.oid);
-      if (oid_tag == ms_nt_principal_name) {
-        // The type of this name is apparently nowhere explicitly
-        // documented. However, in the generated templates, it is always
-        // UTF-8. So try to decode this as UTF-8; if that fails, dump the
-        // raw data.
-        SECItem decoded;
-        if (SEC_ASN1DecodeItem(arena, &decoded,
-                               SEC_ASN1_GET(SEC_UTF8StringTemplate),
-                               &current->name.OthName.name) == SECSuccess) {
-          value = std::string(reinterpret_cast<char*>(decoded.data),
-                              decoded.len);
-        } else {
-          value = ProcessRawBytes(&current->name.OthName.name);
-        }
-        break;
-      } else if (oid_tag == ms_ntds_replication) {
-        // This should be a 16-byte GUID.
-        SECItem guid;
-        if (SEC_ASN1DecodeItem(arena, &guid,
-                               SEC_ASN1_GET(SEC_OctetStringTemplate),
-                               &current->name.OthName.name) == SECSuccess &&
-            guid.len == 16) {
-          unsigned char* d = guid.data;
-          base::SStringPrintf(
-              &value,
-              "{%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-"
-              "%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}",
-              d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6],
-              d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
-        } else {
-          value = ProcessRawBytes(&current->name.OthName.name);
-        }
-      } else {
-        value = ProcessRawBytes(&current->name.OthName.name);
-      }
-      break;
-    }
-    case certRFC822Name:
-      key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_RFC822_NAME);
-      value = std::string(reinterpret_cast<char*>(current->name.other.data),
-                          current->name.other.len);
-      break;
-    case certDNSName:
-      key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_DNS_NAME);
-      value = std::string(reinterpret_cast<char*>(current->name.other.data),
-                          current->name.other.len);
-      value = x509_certificate_model::ProcessIDN(value);
-      break;
-    case certX400Address:
-      key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_X400_ADDRESS);
-      value = ProcessRawBytes(&current->name.other);
-      break;
-    case certDirectoryName:
-      key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_DIRECTORY_NAME);
-      value = ProcessName(&current->name.directoryName);
-      break;
-    case certEDIPartyName:
-      key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_EDI_PARTY_NAME);
-      value = ProcessRawBytes(&current->name.other);
-      break;
-    case certURI:
-      key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_URI);
-      value = std::string(reinterpret_cast<char*>(current->name.other.data),
-                          current->name.other.len);
-      break;
-    case certIPAddress: {
-      key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_IP_ADDRESS);
-
-      net::IPAddress ip(current->name.other.data, current->name.other.len);
-      if (ip.IsValid()) {
-        value = ip.ToString();
-      } else {
-        // Invalid IP address.
-        value = ProcessRawBytes(&current->name.other);
-      }
-      break;
-    }
-    case certRegisterID:
-      key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_REGISTERED_ID);
-      value = DumpOidString(&current->name.other);
-      break;
-  }
-  std::string rv(l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT,
-                                           base::UTF8ToUTF16(key),
-                                           base::UTF8ToUTF16(value)));
-  rv += '\n';
-  return rv;
-}
-
-std::string ProcessGeneralNames(PRArenaPool* arena,
-                                CERTGeneralName* name_list) {
-  std::string rv;
-  CERTGeneralName* current = name_list;
-
-  do {
-    std::string text = ProcessGeneralName(arena, current);
-    if (text.empty())
-      break;
-    rv += text;
-    current = CERT_GetNextGeneralName(current);
-  } while (current != name_list);
-  return rv;
-}
-
-std::string ProcessAltName(SECItem* extension_data) {
-  CERTGeneralName* name_list;
-
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  CHECK(arena.get());
-
-  name_list = CERT_DecodeAltNameExtension(arena.get(), extension_data);
-  if (!name_list)
-    return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
-
-  return ProcessGeneralNames(arena.get(), name_list);
-}
-
-std::string ProcessSubjectKeyId(SECItem* extension_data) {
-  SECItem decoded;
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  CHECK(arena.get());
-
-  std::string rv;
-  if (SEC_QuickDERDecodeItem(arena.get(), &decoded,
-                             SEC_ASN1_GET(SEC_OctetStringTemplate),
-                             extension_data) != SECSuccess) {
-    rv = l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
-    return rv;
-  }
-
-  rv = l10n_util::GetStringFUTF8(IDS_CERT_KEYID_FORMAT,
-                                 base::ASCIIToUTF16(ProcessRawBytes(&decoded)));
-  return rv;
-}
-
-std::string ProcessAuthKeyId(SECItem* extension_data) {
-  CERTAuthKeyID* ret;
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  std::string rv;
-
-  CHECK(arena.get());
-
-  ret = CERT_DecodeAuthKeyID(arena.get(), extension_data);
-
-  if (ret->keyID.len > 0) {
-    rv += l10n_util::GetStringFUTF8(IDS_CERT_KEYID_FORMAT,
-                                    base::ASCIIToUTF16(
-                                        ProcessRawBytes(&ret->keyID)));
-    rv += '\n';
-  }
-
-  if (ret->authCertIssuer) {
-    rv += l10n_util::GetStringFUTF8(
-        IDS_CERT_ISSUER_FORMAT,
-        base::UTF8ToUTF16(
-            ProcessGeneralNames(arena.get(), ret->authCertIssuer)));
-    rv += '\n';
-  }
-
-  if (ret->authCertSerialNumber.len > 0) {
-    rv += l10n_util::GetStringFUTF8(
-        IDS_CERT_SERIAL_NUMBER_FORMAT,
-        base::ASCIIToUTF16(ProcessRawBytes(&ret->authCertSerialNumber)));
-    rv += '\n';
-  }
-
-  return rv;
-}
-
-std::string ProcessUserNotice(SECItem* der_notice) {
-  CERTUserNotice* notice = CERT_DecodeUserNotice(der_notice);
-  if (!notice)
-    return ProcessRawBytes(der_notice);
-
-  std::string rv;
-  if (notice->noticeReference.organization.len != 0) {
-    switch (notice->noticeReference.organization.type) {
-      case siAsciiString:
-      case siVisibleString:
-      case siUTF8String:
-        rv += std::string(
-            reinterpret_cast<char*>(notice->noticeReference.organization.data),
-            notice->noticeReference.organization.len);
-        break;
-      case siBMPString:
-        rv += ProcessBMPString(&notice->noticeReference.organization);
-        break;
-      default:
-        break;
-    }
-    rv += " - ";
-    SECItem** itemList = notice->noticeReference.noticeNumbers;
-    while (*itemList) {
-      unsigned long number;
-      if (SEC_ASN1DecodeInteger(*itemList, &number) == SECSuccess) {
-        if (itemList != notice->noticeReference.noticeNumbers)
-          rv += ", ";
-        rv += '#';
-        rv += base::NumberToString(number);
-      }
-      itemList++;
-    }
-  }
-  if (notice->displayText.len != 0) {
-    rv += "\n    ";
-    switch (notice->displayText.type) {
-      case siAsciiString:
-      case siVisibleString:
-      case siUTF8String:
-        rv += std::string(reinterpret_cast<char*>(notice->displayText.data),
-                          notice->displayText.len);
-        break;
-      case siBMPString:
-        rv += ProcessBMPString(&notice->displayText);
-        break;
-      default:
-        break;
-    }
-  }
-
-  CERT_DestroyUserNotice(notice);
-  return rv;
-}
-
-std::string ProcessCertificatePolicies(SECItem* extension_data) {
-  std::string rv;
-
-  CERTCertificatePolicies* policies = CERT_DecodeCertificatePoliciesExtension(
-      extension_data);
-  if (!policies)
-    return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
-
-  CERTPolicyInfo** policyInfos = policies->policyInfos;
-  while (*policyInfos) {
-    CERTPolicyInfo* policyInfo = *policyInfos++;
-    std::string key = GetOIDText(&policyInfo->policyID);
-
-    // If we have policy qualifiers, display the oid text
-    // with a ':', otherwise just put the oid text and a newline.
-    // TODO(mattm): Add extra note if this is the ev oid?  (It's a bit
-    // complicated, since we don't want to do the EV check synchronously.)
-    if (policyInfo->policyQualifiers) {
-      rv += l10n_util::GetStringFUTF8(IDS_CERT_MULTILINE_INFO_START_FORMAT,
-                                      base::UTF8ToUTF16(key));
-    } else {
-      rv += key;
-    }
-    rv += '\n';
-
-    if (policyInfo->policyQualifiers) {
-      // Add all qualifiers on separate lines, indented.
-      CERTPolicyQualifier** policyQualifiers = policyInfo->policyQualifiers;
-      while (*policyQualifiers != NULL) {
-        rv += "  ";
-
-        CERTPolicyQualifier* policyQualifier = *policyQualifiers++;
-        rv += l10n_util::GetStringFUTF8(
-            IDS_CERT_MULTILINE_INFO_START_FORMAT,
-            base::UTF8ToUTF16(GetOIDText(&policyQualifier->qualifierID)));
-        switch(policyQualifier->oid) {
-          case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
-            rv += "    ";
-            /* The CPS pointer ought to be the cPSuri alternative
-               of the Qualifier choice. */
-            rv += ProcessIA5String(&policyQualifier->qualifierValue);
-            break;
-          case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
-            rv += ProcessUserNotice(&policyQualifier->qualifierValue);
-            break;
-          default:
-            rv += ProcessRawBytes(&policyQualifier->qualifierValue);
-            break;
-        }
-        rv += '\n';
-      }
-    }
-  }
-
-  CERT_DestroyCertificatePoliciesExtension(policies);
-  return rv;
-}
-
-std::string ProcessCrlDistPoints(SECItem* extension_data) {
-  std::string rv;
-  CERTCrlDistributionPoints* crldp;
-  CRLDistributionPoint** points;
-  CRLDistributionPoint* point;
-  bool comma;
-
-  static const struct {
-    int reason;
-    int string_id;
-  } reason_string_map[] = {
-    {RF_UNUSED, IDS_CERT_REVOCATION_REASON_UNUSED},
-    {RF_KEY_COMPROMISE, IDS_CERT_REVOCATION_REASON_KEY_COMPROMISE},
-    {RF_CA_COMPROMISE, IDS_CERT_REVOCATION_REASON_CA_COMPROMISE},
-    {RF_AFFILIATION_CHANGED, IDS_CERT_REVOCATION_REASON_AFFILIATION_CHANGED},
-    {RF_SUPERSEDED, IDS_CERT_REVOCATION_REASON_SUPERSEDED},
-    {RF_CESSATION_OF_OPERATION,
-     IDS_CERT_REVOCATION_REASON_CESSATION_OF_OPERATION},
-    {RF_CERTIFICATE_HOLD, IDS_CERT_REVOCATION_REASON_CERTIFICATE_HOLD},
-  };
-
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  CHECK(arena.get());
-
-  crldp = CERT_DecodeCRLDistributionPoints(arena.get(), extension_data);
-  if (!crldp || !crldp->distPoints) {
-    rv = l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
-    return rv;
-  }
-
-  for (points = crldp->distPoints; *points; ++points) {
-    point = *points;
-    switch (point->distPointType) {
-      case generalName:
-        // generalName is a typo in upstream NSS; fullName is actually a
-        // GeneralNames (SEQUENCE OF GeneralName). See Mozilla Bug #615100.
-        rv += ProcessGeneralNames(arena.get(), point->distPoint.fullName);
-        break;
-      case relativeDistinguishedName:
-        rv += ProcessRDN(&point->distPoint.relativeName);
-        break;
-    }
-    if (point->reasons.len) {
-      rv += ' ';
-      comma = false;
-      for (size_t i = 0; i < std::size(reason_string_map); ++i) {
-        if (point->reasons.data[0] & reason_string_map[i].reason) {
-          if (comma)
-            rv += ',';
-          rv += l10n_util::GetStringUTF8(reason_string_map[i].string_id);
-          comma = true;
-        }
-      }
-      rv += '\n';
-    }
-    if (point->crlIssuer) {
-      rv += l10n_util::GetStringFUTF8(
-          IDS_CERT_ISSUER_FORMAT,
-          base::UTF8ToUTF16(
-              ProcessGeneralNames(arena.get(), point->crlIssuer)));
-    }
-  }
-  return rv;
-}
-
-std::string ProcessAuthInfoAccess(SECItem* extension_data) {
-  std::string rv;
-  CERTAuthInfoAccess** aia;
-  CERTAuthInfoAccess* desc;
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  CHECK(arena.get());
-
-  aia = CERT_DecodeAuthInfoAccessExtension(arena.get(), extension_data);
-  if (aia == NULL)
-    return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
-
-  while (*aia != NULL) {
-    desc = *aia++;
-    std::u16string location_str =
-        base::UTF8ToUTF16(ProcessGeneralName(arena.get(), desc->location));
-    switch (SECOID_FindOIDTag(&desc->method)) {
-    case SEC_OID_PKIX_OCSP:
-      rv += l10n_util::GetStringFUTF8(IDS_CERT_OCSP_RESPONDER_FORMAT,
-                                      location_str);
-      break;
-    case SEC_OID_PKIX_CA_ISSUERS:
-      rv += l10n_util::GetStringFUTF8(IDS_CERT_CA_ISSUERS_FORMAT,
-                                      location_str);
-      break;
-    default:
-      rv += l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT,
-                                      base::UTF8ToUTF16(
-                                          GetOIDText(&desc->method)),
-                                      location_str);
-      break;
-    }
-  }
-  return rv;
-}
-
-std::string ProcessIA5String(SECItem* extension_data) {
-  SECItem item;
-  if (SEC_ASN1DecodeItem(NULL, &item, SEC_ASN1_GET(SEC_IA5StringTemplate),
-                         extension_data) != SECSuccess)
-    return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
-  std::string rv((char*)item.data, item.len);  // ASCII data.
-  PORT_Free(item.data);
-  return rv;
-}
-
-std::string ProcessBMPString(SECItem* extension_data) {
-  std::string rv;
-  SECItem item;
-  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  CHECK(arena.get());
-
-  if (SEC_ASN1DecodeItem(arena.get(), &item,
-                         SEC_ASN1_GET(SEC_BMPStringTemplate), extension_data) ==
-      SECSuccess)
-    rv = BMPtoUTF8(arena.get(), item.data, item.len);
-  return rv;
-}
-
-struct MaskIdPair {
-  unsigned int mask;
-  int string_id;
-};
-
-static std::string ProcessBitField(SECItem* bitfield,
-                                   const MaskIdPair* string_map,
-                                   size_t len,
-                                   char separator) {
-  unsigned int bits = 0;
-  std::string rv;
-  for (size_t i = 0; i * 8 < bitfield->len && i < sizeof(bits); ++i)
-    bits |= bitfield->data[i] << (i * 8);
-  for (size_t i = 0; i < len; ++i) {
-    if (bits & string_map[i].mask) {
-      if (!rv.empty())
-        rv += separator;
-      rv += l10n_util::GetStringUTF8(string_map[i].string_id);
-    }
-  }
-  return rv;
-}
-
-static std::string ProcessBitStringExtension(SECItem* extension_data,
-                                             const MaskIdPair* string_map,
-                                             size_t len,
-                                             char separator) {
-  SECItem decoded;
-  decoded.type = siBuffer;
-  decoded.data = NULL;
-  decoded.len  = 0;
-  if (SEC_ASN1DecodeItem(NULL, &decoded, SEC_ASN1_GET(SEC_BitStringTemplate),
-                         extension_data) != SECSuccess)
-    return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
-  std::string rv = ProcessBitField(&decoded, string_map, len, separator);
-  PORT_Free(decoded.data);
-  return rv;
-}
-
-std::string ProcessNSCertTypeExtension(SECItem* extension_data) {
-  static const MaskIdPair usage_string_map[] = {
-    {NS_CERT_TYPE_SSL_CLIENT, IDS_CERT_USAGE_SSL_CLIENT},
-    {NS_CERT_TYPE_SSL_SERVER, IDS_CERT_USAGE_SSL_SERVER},
-    {NS_CERT_TYPE_EMAIL, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL},
-    {NS_CERT_TYPE_OBJECT_SIGNING, IDS_CERT_USAGE_OBJECT_SIGNER},
-    {NS_CERT_TYPE_SSL_CA, IDS_CERT_USAGE_SSL_CA},
-    {NS_CERT_TYPE_EMAIL_CA, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL_CA},
-    {NS_CERT_TYPE_OBJECT_SIGNING_CA, IDS_CERT_USAGE_OBJECT_SIGNER},
-  };
-  return ProcessBitStringExtension(extension_data, usage_string_map,
-                                   std::size(usage_string_map), '\n');
-}
-
-static const MaskIdPair key_usage_string_map[] = {
-  {KU_DIGITAL_SIGNATURE, IDS_CERT_X509_KEY_USAGE_SIGNING},
-  {KU_NON_REPUDIATION, IDS_CERT_X509_KEY_USAGE_NONREP},
-  {KU_KEY_ENCIPHERMENT, IDS_CERT_X509_KEY_USAGE_ENCIPHERMENT},
-  {KU_DATA_ENCIPHERMENT, IDS_CERT_X509_KEY_USAGE_DATA_ENCIPHERMENT},
-  {KU_KEY_AGREEMENT, IDS_CERT_X509_KEY_USAGE_KEY_AGREEMENT},
-  {KU_KEY_CERT_SIGN, IDS_CERT_X509_KEY_USAGE_CERT_SIGNER},
-  {KU_CRL_SIGN, IDS_CERT_X509_KEY_USAGE_CRL_SIGNER},
-  {KU_ENCIPHER_ONLY, IDS_CERT_X509_KEY_USAGE_ENCIPHER_ONLY},
-  // NSS is missing a flag for dechiperOnly, see:
-  // https://bugzilla.mozilla.org/show_bug.cgi?id=549952
-};
-
-std::string ProcessKeyUsageBitString(SECItem* bitstring, char sep) {
-  return ProcessBitField(bitstring, key_usage_string_map,
-                         std::size(key_usage_string_map), sep);
-}
-
-std::string ProcessKeyUsageExtension(SECItem* extension_data) {
-  return ProcessBitStringExtension(extension_data, key_usage_string_map,
-                                   std::size(key_usage_string_map), '\n');
-}
-
-std::string ProcessExtKeyUsage(SECItem* extension_data) {
-  std::string rv;
-  CERTOidSequence* extension_key_usage = NULL;
-  extension_key_usage = CERT_DecodeOidSequence(extension_data);
-  if (extension_key_usage == NULL)
-    return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
-
-  SECItem** oids;
-  SECItem* oid;
-  for (oids = extension_key_usage->oids; oids != NULL && *oids != NULL;
-       ++oids) {
-    oid = *oids;
-    std::string oid_dump = DumpOidString(oid);
-    std::string oid_text = GetOIDText(oid);
-
-    // If oid is one we recognize, oid_text will have a text description of the
-    // OID, which we display along with the oid_dump.  If we don't recognize the
-    // OID, GetOIDText will return the same value as DumpOidString, so just
-    // display the OID alone.
-    if (oid_dump == oid_text)
-      rv += oid_dump;
-    else
-      rv += l10n_util::GetStringFUTF8(IDS_CERT_EXT_KEY_USAGE_FORMAT,
-                                      base::UTF8ToUTF16(oid_text),
-                                      base::UTF8ToUTF16(oid_dump));
-    rv += '\n';
-  }
-  CERT_DestroyOidSequence(extension_key_usage);
-  return rv;
-}
-
-std::string ProcessExtensionData(CERTCertExtension* extension) {
-  g_dynamic_oid_registerer.Get();
-  SECOidTag oid_tag = SECOID_FindOIDTag(&extension->id);
-  SECItem* extension_data = &extension->value;
-
-  // This (and its sub-functions) are based on the same-named functions in
-  // security/manager/ssl/src/nsNSSCertHelper.cpp.
-  switch (oid_tag) {
-    case SEC_OID_NS_CERT_EXT_CERT_TYPE:
-      return ProcessNSCertTypeExtension(extension_data);
-    case SEC_OID_X509_KEY_USAGE:
-      return ProcessKeyUsageExtension(extension_data);
-    case SEC_OID_X509_BASIC_CONSTRAINTS:
-      return ProcessBasicConstraints(extension_data);
-    case SEC_OID_X509_EXT_KEY_USAGE:
-      return ProcessExtKeyUsage(extension_data);
-    case SEC_OID_X509_ISSUER_ALT_NAME:
-    case SEC_OID_X509_SUBJECT_ALT_NAME:
-      return ProcessAltName(extension_data);
-    case SEC_OID_X509_SUBJECT_KEY_ID:
-      return ProcessSubjectKeyId(extension_data);
-    case SEC_OID_X509_AUTH_KEY_ID:
-      return ProcessAuthKeyId(extension_data);
-    case SEC_OID_X509_CERTIFICATE_POLICIES:
-      return ProcessCertificatePolicies(extension_data);
-    case SEC_OID_X509_CRL_DIST_POINTS:
-      return ProcessCrlDistPoints(extension_data);
-    case SEC_OID_X509_AUTH_INFO_ACCESS:
-      return ProcessAuthInfoAccess(extension_data);
-    case SEC_OID_NS_CERT_EXT_BASE_URL:
-    case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
-    case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
-    case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
-    case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
-    case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
-    case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
-    case SEC_OID_NS_CERT_EXT_COMMENT:
-    case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
-    case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
-      return ProcessIA5String(extension_data);
-    default:
-      if (oid_tag == ms_cert_ext_certtype)
-        return ProcessBMPString(extension_data);
-      return ProcessRawBytes(extension_data);
-  }
-}
-
-std::string ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo* spki) {
-  std::string rv;
-  SECKEYPublicKey* key = SECKEY_ExtractPublicKey(spki);
-  if (key) {
-    switch (key->keyType) {
-      case rsaKey: {
-        rv = l10n_util::GetStringFUTF8(
-            IDS_CERT_RSA_PUBLIC_KEY_DUMP_FORMAT,
-            base::NumberToString16(key->u.rsa.modulus.len * 8),
-            base::UTF8ToUTF16(ProcessRawBytes(&key->u.rsa.modulus)),
-            base::NumberToString16(key->u.rsa.publicExponent.len * 8),
-            base::UTF8ToUTF16(ProcessRawBytes(&key->u.rsa.publicExponent)));
-        break;
-      }
-      default:
-        rv = x509_certificate_model::ProcessRawBits(
-            spki->subjectPublicKey.data, spki->subjectPublicKey.len);
-        break;
-    }
-    SECKEY_DestroyPublicKey(key);
-  }
-  return rv;
-}
-
 net::CertType GetCertType(CERTCertificate *cert) {
   CERTCertTrust trust = {0};
   CERT_GetCertTrust(cert, &trust);
diff --git a/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h b/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h
index 3a5ebb5..ca3db8f9 100644
--- a/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h
+++ b/chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h
@@ -43,37 +43,10 @@
 
 #include <cert.h>
 
-#include <string>
-
-#include "net/cert/cert_database.h"
 #include "net/cert/cert_type.h"
 
 namespace mozilla_security_manager {
 
-std::string DumpOidString(SECItem* oid);
-std::string GetOIDText(SECItem* oid);
-
-std::string ProcessRDN(CERTRDN* rdn);
-std::string ProcessName(CERTName* name);
-std::string ProcessBasicConstraints(SECItem* extension_data);
-std::string ProcessGeneralName(PRArenaPool* arena,
-                               CERTGeneralName* current);
-std::string ProcessGeneralNames(PRArenaPool* arena,
-                                CERTGeneralName* name_list);
-std::string ProcessAltName(SECItem* extension_data);
-std::string ProcessSubjectKeyId(SECItem* extension_data);
-std::string ProcessAuthKeyId(SECItem* extension_data);
-std::string ProcessCrlDistPoints(SECItem* extension_data);
-std::string ProcessAuthInfoAccess(SECItem* extension_data);
-std::string ProcessIA5String(SECItem* extension_data);
-std::string ProcessBMPString(SECItem* extension_data);
-std::string ProcessNSCertTypeExtension(SECItem* extension_data);
-std::string ProcessKeyUsageBitString(SECItem* bitstring, char sep);
-std::string ProcessKeyUsageExtension(SECItem* extension_data);
-std::string ProcessExtKeyUsage(SECItem* extension_data);
-std::string ProcessExtensionData(CERTCertExtension* extension);
-std::string ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo* spki);
-
 net::CertType GetCertType(CERTCertificate *cert);
 
 }  // namespace mozilla_security_manager
diff --git a/chrome/updater/persisted_data.cc b/chrome/updater/persisted_data.cc
index cae322df..7c92251 100644
--- a/chrome/updater/persisted_data.cc
+++ b/chrome/updater/persisted_data.cc
@@ -4,9 +4,13 @@
 
 #include "chrome/updater/persisted_data.h"
 
+#include <vector>
+
+#include "base/base64.h"
 #include "base/check_op.h"
 #include "base/files/file_path.h"
 #include "base/sequence_checker.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "base/values.h"
@@ -16,6 +20,13 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+#if BUILDFLAG(IS_WIN)
+#include <windows.h>
+
+#include "chrome/updater/win/win_util.h"
+#endif
 
 namespace {
 
@@ -34,6 +45,7 @@
 // TODO(crbug.com/1292189): rename "updater_time" to "last_checked".
 constexpr char kLastChecked[] = "update_time";
 constexpr char kLastStarted[] = "last_started";
+constexpr char kLastOSVersion[] = "last_os_version";
 
 }  // namespace
 
@@ -237,12 +249,55 @@
     pref_service_->SetTime(kLastStarted, time);
 }
 
+#if BUILDFLAG(IS_WIN)
+absl::optional<OSVERSIONINFOEX> PersistedData::GetLastOSVersion() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  // Unpacks the os version from a base-64-encoded string internally.
+  const std::string encoded_os_version =
+      pref_service_->GetString(kLastOSVersion);
+
+  if (encoded_os_version.empty())
+    return absl::nullopt;
+
+  const absl::optional<std::vector<uint8_t>> decoded_os_version =
+      base::Base64Decode(encoded_os_version);
+  if (!decoded_os_version ||
+      decoded_os_version->size() != sizeof(OSVERSIONINFOEX)) {
+    return absl::nullopt;
+  }
+
+  return *reinterpret_cast<const OSVERSIONINFOEX*>(decoded_os_version->data());
+}
+
+void PersistedData::SetLastOSVersion() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!pref_service_)
+    return;
+
+  // Get and set the current OS version.
+  absl::optional<OSVERSIONINFOEX> os_version = GetOSVersion();
+  if (!os_version)
+    return;
+
+  // The os version is internally stored as a base-64-encoded string.
+  std::string encoded_os_version;
+  base::Base64Encode(
+      base::StringPiece(reinterpret_cast<const char*>(&os_version.value()),
+                        sizeof(OSVERSIONINFOEX)),
+      &encoded_os_version);
+  return pref_service_->SetString(kLastOSVersion, encoded_os_version);
+}
+#endif
+
 // Register persisted data prefs, except for kPersistedDataPreference.
 // kPersistedDataPreference is registered by update_client::RegisterPrefs.
 void RegisterPersistedDataPrefs(scoped_refptr<PrefRegistrySimple> registry) {
   registry->RegisterBooleanPref(kHadApps, false);
   registry->RegisterTimePref(kLastChecked, {});
   registry->RegisterTimePref(kLastStarted, {});
+  registry->RegisterStringPref(kLastOSVersion, {});
 }
 
 }  // namespace updater
diff --git a/chrome/updater/persisted_data.h b/chrome/updater/persisted_data.h
index 3547de0..ecf552a 100644
--- a/chrome/updater/persisted_data.h
+++ b/chrome/updater/persisted_data.h
@@ -12,6 +12,11 @@
 #include "base/memory/ref_counted.h"
 #include "base/sequence_checker.h"
 #include "base/values.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+#if BUILDFLAG(IS_WIN)
+#include <windows.h>
+#endif
 
 class PrefService;
 class PrefRegistrySimple;
@@ -98,6 +103,14 @@
   base::Time GetLastStarted() const;
   void SetLastStarted(const base::Time& time);
 
+#if BUILDFLAG(IS_WIN)
+  // Retrieves the previously stored OS version.
+  absl::optional<OSVERSIONINFOEX> GetLastOSVersion() const;
+
+  // Stores the current os version.
+  void SetLastOSVersion();
+#endif
+
  private:
   friend class base::RefCountedThreadSafe<PersistedData>;
   ~PersistedData();
diff --git a/chrome/updater/persisted_data_unittest.cc b/chrome/updater/persisted_data_unittest.cc
index 297d9be..0e502c6 100644
--- a/chrome/updater/persisted_data_unittest.cc
+++ b/chrome/updater/persisted_data_unittest.cc
@@ -17,6 +17,10 @@
 #include "components/update_client/update_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if BUILDFLAG(IS_WIN)
+#include <windows.h>
+#endif
+
 namespace updater {
 
 TEST(PersistedDataTest, Simple) {
@@ -126,4 +130,38 @@
   EXPECT_TRUE(metadata->GetAppIds().empty());
 }
 
+#if BUILDFLAG(IS_WIN)
+TEST(PersistedDataTest, LastOSVersion) {
+  auto pref = std::make_unique<TestingPrefServiceSimple>();
+  update_client::RegisterPrefs(pref->registry());
+  RegisterPersistedDataPrefs(pref->registry());
+  auto metadata = base::MakeRefCounted<PersistedData>(pref.get());
+
+  EXPECT_EQ(metadata->GetLastOSVersion(), absl::nullopt);
+
+  // This will persist the current OS version into the persisted data.
+  metadata->SetLastOSVersion();
+  EXPECT_NE(metadata->GetLastOSVersion(), absl::nullopt);
+
+  // Compare the persisted data OS version to the version from `::GetVersionEx`.
+  const OSVERSIONINFOEX metadata_os = metadata->GetLastOSVersion().value();
+
+  OSVERSIONINFOEX os = {};
+  os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+  EXPECT_TRUE(::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&os)));
+
+  EXPECT_EQ(metadata_os.dwOSVersionInfoSize, os.dwOSVersionInfoSize);
+  EXPECT_EQ(metadata_os.dwMajorVersion, os.dwMajorVersion);
+  EXPECT_EQ(metadata_os.dwMinorVersion, os.dwMinorVersion);
+  EXPECT_EQ(metadata_os.dwBuildNumber, os.dwBuildNumber);
+  EXPECT_EQ(metadata_os.dwPlatformId, os.dwPlatformId);
+  EXPECT_STREQ(metadata_os.szCSDVersion, os.szCSDVersion);
+  EXPECT_EQ(metadata_os.wServicePackMajor, os.wServicePackMajor);
+  EXPECT_EQ(metadata_os.wServicePackMinor, os.wServicePackMinor);
+  EXPECT_EQ(metadata_os.wSuiteMask, os.wSuiteMask);
+  EXPECT_EQ(metadata_os.wProductType, os.wProductType);
+  EXPECT_EQ(metadata_os.wReserved, os.wReserved);
+}
+#endif
+
 }  // namespace updater
diff --git a/chrome/updater/win/win_util.cc b/chrome/updater/win/win_util.cc
index 08e8886..9ede349 100644
--- a/chrome/updater/win/win_util.cc
+++ b/chrome/updater/win/win_util.cc
@@ -752,4 +752,24 @@
                                         : HKEY_CURRENT_USER;
 }
 
+absl::optional<OSVERSIONINFOEX> GetOSVersion() {
+  // `::RtlGetVersion` is being used here instead of `::GetVersionEx`, because
+  // the latter function can return the incorrect version if it is shimmed using
+  // an app compat shim.
+  using RtlGetVersion = LONG(WINAPI*)(OSVERSIONINFOEX*);
+  static const RtlGetVersion rtl_get_version = reinterpret_cast<RtlGetVersion>(
+      ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "RtlGetVersion"));
+  if (!rtl_get_version)
+    return absl::nullopt;
+
+  OSVERSIONINFOEX os_out = {};
+  os_out.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+
+  rtl_get_version(&os_out);
+  if (!os_out.dwMajorVersion)
+    return absl::nullopt;
+
+  return os_out;
+}
+
 }  // namespace updater
diff --git a/chrome/updater/win/win_util.h b/chrome/updater/win/win_util.h
index 2049d00a..70a9d1c 100644
--- a/chrome/updater/win/win_util.h
+++ b/chrome/updater/win/win_util.h
@@ -256,6 +256,9 @@
 // * scope == UpdaterScope::kUser == HKEY_CURRENT_USER
 HKEY UpdaterScopeToHKeyRoot(UpdaterScope scope);
 
+// Returns an OSVERSIONINFOEX for the current OS version.
+absl::optional<OSVERSIONINFOEX> GetOSVersion();
+
 }  // namespace updater
 
 #endif  // CHROME_UPDATER_WIN_WIN_UTIL_H_
diff --git a/chrome/updater/win/win_util_unittest.cc b/chrome/updater/win/win_util_unittest.cc
index 7dd97f2a..9bcb6f66 100644
--- a/chrome/updater/win/win_util_unittest.cc
+++ b/chrome/updater/win/win_util_unittest.cc
@@ -137,4 +137,26 @@
   EXPECT_EQ(exit_code, 0UL);
 }
 
+TEST(WinUtil, GetOSVersion) {
+  absl::optional<OSVERSIONINFOEX> rtl_os_version = GetOSVersion();
+  ASSERT_NE(rtl_os_version, absl::nullopt);
+
+  // Compare to the version from `::GetVersionEx`.
+  OSVERSIONINFOEX os = {};
+  os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+  EXPECT_TRUE(::GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&os)));
+
+  EXPECT_EQ(rtl_os_version->dwOSVersionInfoSize, os.dwOSVersionInfoSize);
+  EXPECT_EQ(rtl_os_version->dwMajorVersion, os.dwMajorVersion);
+  EXPECT_EQ(rtl_os_version->dwMinorVersion, os.dwMinorVersion);
+  EXPECT_EQ(rtl_os_version->dwBuildNumber, os.dwBuildNumber);
+  EXPECT_EQ(rtl_os_version->dwPlatformId, os.dwPlatformId);
+  EXPECT_STREQ(rtl_os_version->szCSDVersion, os.szCSDVersion);
+  EXPECT_EQ(rtl_os_version->wServicePackMajor, os.wServicePackMajor);
+  EXPECT_EQ(rtl_os_version->wServicePackMinor, os.wServicePackMinor);
+  EXPECT_EQ(rtl_os_version->wSuiteMask, os.wSuiteMask);
+  EXPECT_EQ(rtl_os_version->wProductType, os.wProductType);
+  EXPECT_EQ(rtl_os_version->wReserved, os.wReserved);
+}
+
 }  // namespace updater
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 5ab7885..ca6f630 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -3407,6 +3407,9 @@
       <message name="IDS_FEEDBACK_TOOL_USER_EMAIL_LABEL" desc="Label showing the e-mail address that will be reported.">
         Email
       </message>
+      <message name="IDS_FEEDBACK_TOOL_SHARE_DIAGNOSTIC_DATA_LABEL" desc="Label showing the share diagnostic data.">
+        Share diagnostic data
+      </message>
       <!-- Confirmation Page -->
       <message name="IDS_FEEDBACK_TOOL_PAGE_TITLE_AFTER_SENT" desc="Label showing a thank you message as the title of the confirmation page after a report has been sent.">
         Thanks for your feedback
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_SHARE_DIAGNOSTIC_DATA_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_SHARE_DIAGNOSTIC_DATA_LABEL.png.sha1
new file mode 100644
index 0000000..009d7f2
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_SHARE_DIAGNOSTIC_DATA_LABEL.png.sha1
@@ -0,0 +1 @@
+e9bd08c14675a2d4c7e76314ce02fcbb1bebc0f1
\ No newline at end of file
diff --git a/chromeos/dbus/arc/arc_appfuse_provider_client.cc b/chromeos/dbus/arc/arc_appfuse_provider_client.cc
index 70ad078..3f23f08b 100644
--- a/chromeos/dbus/arc/arc_appfuse_provider_client.cc
+++ b/chromeos/dbus/arc/arc_appfuse_provider_client.cc
@@ -9,7 +9,9 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
+#include "base/check_op.h"
 #include "base/logging.h"
+#include "chromeos/dbus/arc/fake_arc_appfuse_provider_client.h"
 #include "dbus/bus.h"
 #include "dbus/message.h"
 #include "dbus/object_proxy.h"
@@ -19,9 +21,11 @@
 
 namespace {
 
+ArcAppfuseProviderClient* g_instance = nullptr;
+
 class ArcAppfuseProviderClientImpl : public ArcAppfuseProviderClient {
  public:
-  ArcAppfuseProviderClientImpl() {}
+  ArcAppfuseProviderClientImpl() = default;
 
   ArcAppfuseProviderClientImpl(const ArcAppfuseProviderClientImpl&) = delete;
   ArcAppfuseProviderClientImpl& operator=(const ArcAppfuseProviderClientImpl&) =
@@ -76,7 +80,6 @@
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
- protected:
   // DBusClient override.
   void Init(dbus::Bus* bus) override {
     proxy_ = bus->GetObjectProxy(
@@ -114,13 +117,36 @@
 
 }  // namespace
 
-ArcAppfuseProviderClient::ArcAppfuseProviderClient() = default;
-
-ArcAppfuseProviderClient::~ArcAppfuseProviderClient() = default;
+// static
+ArcAppfuseProviderClient* ArcAppfuseProviderClient::Get() {
+  return g_instance;
+}
 
 // static
-std::unique_ptr<ArcAppfuseProviderClient> ArcAppfuseProviderClient::Create() {
-  return std::make_unique<ArcAppfuseProviderClientImpl>();
+void ArcAppfuseProviderClient::Initialize(dbus::Bus* bus) {
+  CHECK(bus);
+  (new ArcAppfuseProviderClientImpl())->Init(bus);
+}
+
+// static
+void ArcAppfuseProviderClient::InitializeFake() {
+  new FakeArcAppfuseProviderClient();
+}
+
+// static
+void ArcAppfuseProviderClient::Shutdown() {
+  CHECK(g_instance);
+  delete g_instance;
+}
+
+ArcAppfuseProviderClient::ArcAppfuseProviderClient() {
+  CHECK(!g_instance);
+  g_instance = this;
+}
+
+ArcAppfuseProviderClient::~ArcAppfuseProviderClient() {
+  CHECK_EQ(g_instance, this);
+  g_instance = nullptr;
 }
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/arc/arc_appfuse_provider_client.h b/chromeos/dbus/arc/arc_appfuse_provider_client.h
index f231eba..f1184aa 100644
--- a/chromeos/dbus/arc/arc_appfuse_provider_client.h
+++ b/chromeos/dbus/arc/arc_appfuse_provider_client.h
@@ -7,14 +7,11 @@
 
 #include <stdint.h>
 
-#include <memory>
-
 #include "base/component_export.h"
+#include "base/files/scoped_file.h"
 #include "chromeos/dbus/common/dbus_client.h"
 #include "chromeos/dbus/common/dbus_method_call_status.h"
 
-#include "base/files/scoped_file.h"
-
 namespace chromeos {
 
 // ArcAppfuseProviderClient is used to communicate with the ArcAppfuseProvider
@@ -24,12 +21,17 @@
 class COMPONENT_EXPORT(CHROMEOS_DBUS_ARC) ArcAppfuseProviderClient
     : public DBusClient {
  public:
-  ArcAppfuseProviderClient();
-  ~ArcAppfuseProviderClient() override;
+  // Returns the global instance if initialized. May return null.
+  static ArcAppfuseProviderClient* Get();
 
-  // Factory function, creates a new instance.
-  // For normal usage, access the singleton via DBusThreadManager::Get().
-  static std::unique_ptr<ArcAppfuseProviderClient> Create();
+  // Creates and initializes the global instance. |bus| must not be null.
+  static void Initialize(dbus::Bus* bus);
+
+  // Creates and initializes a fake global instance.
+  static void InitializeFake();
+
+  // Destroys the global instance if it has been initialized.
+  static void Shutdown();
 
   // Mounts a new appfuse file system and returns a filtered /dev/fuse FD
   // associated with the mounted file system.
@@ -48,6 +50,10 @@
                         int32_t file_id,
                         int32_t flags,
                         DBusMethodCallback<base::ScopedFD> callback) = 0;
+
+ protected:
+  ArcAppfuseProviderClient();
+  ~ArcAppfuseProviderClient() override;
 };
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/dbus_clients_browser.cc b/chromeos/dbus/dbus_clients_browser.cc
index c0fa5c7..a8fc24e 100644
--- a/chromeos/dbus/dbus_clients_browser.cc
+++ b/chromeos/dbus/dbus_clients_browser.cc
@@ -71,8 +71,6 @@
       use_real_clients ? REAL_DBUS_CLIENT_IMPLEMENTATION
                        : FAKE_DBUS_CLIENT_IMPLEMENTATION;
 
-  arc_appfuse_provider_client_ =
-      CREATE_DBUS_CLIENT(ArcAppfuseProviderClient, use_real_clients);
   arc_data_snapshotd_client_ =
       CREATE_DBUS_CLIENT(ArcDataSnapshotdClient, use_real_clients);
   arc_keymaster_client_ =
@@ -117,7 +115,6 @@
 void DBusClientsBrowser::Initialize(dbus::Bus* system_bus) {
   DCHECK(DBusThreadManager::IsInitialized());
 
-  arc_appfuse_provider_client_->Init(system_bus);
   arc_data_snapshotd_client_->Init(system_bus);
   arc_keymaster_client_->Init(system_bus);
   arc_midis_client_->Init(system_bus);
diff --git a/chromeos/dbus/dbus_clients_browser.h b/chromeos/dbus/dbus_clients_browser.h
index 8d9efd3..82e589f 100644
--- a/chromeos/dbus/dbus_clients_browser.h
+++ b/chromeos/dbus/dbus_clients_browser.h
@@ -15,7 +15,6 @@
 
 namespace chromeos {
 
-class ArcAppfuseProviderClient;
 class ArcDataSnapshotdClient;
 class ArcKeymasterClient;
 class ArcMidisClient;
@@ -58,7 +57,6 @@
   friend class DBusThreadManager;
   friend class DBusThreadManagerSetter;
 
-  std::unique_ptr<ArcAppfuseProviderClient> arc_appfuse_provider_client_;
   std::unique_ptr<ArcDataSnapshotdClient> arc_data_snapshotd_client_;
   std::unique_ptr<ArcKeymasterClient> arc_keymaster_client_;
   std::unique_ptr<ArcMidisClient> arc_midis_client_;
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc
index 7b8adfbf..edcace9 100644
--- a/chromeos/dbus/dbus_thread_manager.cc
+++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -51,11 +51,6 @@
              ? g_setter->name.get()   \
              : (clients_browser_ ? clients_browser_->name.get() : nullptr)
 
-ArcAppfuseProviderClient* DBusThreadManager::GetArcAppfuseProviderClient() {
-  return clients_browser_ ? clients_browser_->arc_appfuse_provider_client_.get()
-                          : nullptr;
-}
-
 ArcDataSnapshotdClient* DBusThreadManager::GetArcDataSnapshotdClient() {
   return clients_browser_ ? clients_browser_->arc_data_snapshotd_client_.get()
                           : nullptr;
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h
index 5ff72ef3..e50e35d 100644
--- a/chromeos/dbus/dbus_thread_manager.h
+++ b/chromeos/dbus/dbus_thread_manager.h
@@ -15,7 +15,6 @@
 namespace chromeos {
 
 // Style Note: Clients are sorted by names.
-class ArcAppfuseProviderClient;
 class ArcDataSnapshotdClient;
 class ArcKeymasterClient;
 class ArcMidisClient;
@@ -73,7 +72,6 @@
   // pointers after DBusThreadManager has been shut down.
   // TODO(jamescook): Replace this with calls to FooClient::Get().
   // http://crbug.com/647367
-  ArcAppfuseProviderClient* GetArcAppfuseProviderClient();
   ArcDataSnapshotdClient* GetArcDataSnapshotdClient();
   ArcKeymasterClient* GetArcKeymasterClient();
   ArcMidisClient* GetArcMidisClient();
diff --git a/components/android_autofill/browser/junit/BUILD.gn b/components/android_autofill/browser/junit/BUILD.gn
index a063958..62608cce 100644
--- a/components/android_autofill/browser/junit/BUILD.gn
+++ b/components/android_autofill/browser/junit/BUILD.gn
@@ -5,9 +5,7 @@
 import("//build/config/android/config.gni")
 import("//build/config/android/rules.gni")
 
-java_library("components_autofill_junit_tests") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("components_autofill_junit_tests") {
   testonly = true
   sources = [ "src/org/chromium/components/autofill/AutofillProviderTest.java" ]
   deps = [
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc
index 3d4e11db..9470cfb3 100644
--- a/components/autofill/core/common/autofill_payments_features.cc
+++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -53,6 +53,15 @@
 const base::Feature kAutofillCreditCardUploadFeedback{
     "AutofillCreditCardUploadFeedback", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// When enabled, the GetDetailsForEnrollResponseDetails in the
+// UploadCardResponseDetails will be parsed, which will allow the Virtual Card
+// Enrollment flow to skip making a new GetDetailsForEnroll request. This is an
+// optimization to improve the latency of the Virtual Card Enrollment flow.
+const base::Feature
+    kAutofillEnableGetDetailsForEnrollParsingInUploadCardResponse{
+        "AutofillEnableGetDetailsForEnrollParsingInUploadCardResponse",
+        base::FEATURE_ENABLED_BY_DEFAULT};
+
 // When enabled, enable manual falling component for virtual cards on Android.
 const base::Feature kAutofillEnableManualFallbackForVirtualCards{
     "AutofillEnableManualFallbackForVirtualCards",
@@ -98,7 +107,7 @@
 // autofill flows (for example, downstream and upstream), and from the settings
 // page.
 const base::Feature kAutofillEnableUpdateVirtualCardEnrollment{
-    "AutofillEnableUpdateVirtualCardEnrollment",
+  "AutofillEnableUpdateVirtualCardEnrollment",
 #if BUILDFLAG(IS_IOS)
       base::FEATURE_DISABLED_BY_DEFAULT
 #else
diff --git a/components/autofill/core/common/autofill_payments_features.h b/components/autofill/core/common/autofill_payments_features.h
index aaa4ff0..96a9677 100644
--- a/components/autofill/core/common/autofill_payments_features.h
+++ b/components/autofill/core/common/autofill_payments_features.h
@@ -21,6 +21,8 @@
 extern const base::Feature kAutofillAutoTriggerManualFallbackForCards;
 extern const base::Feature kAutofillCreditCardAuthentication;
 extern const base::Feature kAutofillCreditCardUploadFeedback;
+extern const base::Feature
+    kAutofillEnableGetDetailsForEnrollParsingInUploadCardResponse;
 extern const base::Feature kAutofillEnableManualFallbackForVirtualCards;
 extern const base::Feature kAutofillEnableOfferNotificationForPromoCodes;
 extern const base::Feature kAutofillEnableOffersInClankKeyboardAccessory;
diff --git a/components/background_task_scheduler/BUILD.gn b/components/background_task_scheduler/BUILD.gn
index 4417a697..0d73ea8 100644
--- a/components/background_task_scheduler/BUILD.gn
+++ b/components/background_task_scheduler/BUILD.gn
@@ -99,9 +99,8 @@
     ]
   }
 
-  java_library("components_background_task_scheduler_junit_tests") {
-    # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-    bypass_platform_checks = true
+  robolectric_library("components_background_task_scheduler_junit_tests") {
+    include_android_sdk = false
     testonly = true
     sources = [
       "internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskGcmTaskServiceTest.java",
@@ -136,6 +135,7 @@
       "//third_party/android_deps:robolectric_all_java",
       "//third_party/junit",
       "//third_party/mockito:mockito_java",
+      "//third_party/robolectric:robolectric_test_sdk_java",
     ]
   }
 }
diff --git a/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskJobServiceTest.java b/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskJobServiceTest.java
index 90c0fd2..f308e92 100644
--- a/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskJobServiceTest.java
+++ b/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskJobServiceTest.java
@@ -11,6 +11,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.job.JobParameters;
+import android.os.Build;
 import android.os.PersistableBundle;
 
 import org.junit.Before;
@@ -29,7 +30,7 @@
 
 /** Unit tests for {@link BackgroundTaskJobService}. */
 @RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
+@Config(manifest = Config.NONE, sdk = Build.VERSION_CODES.S)
 public class BackgroundTaskJobServiceTest {
     private static BackgroundTaskSchedulerJobService.Clock sClock = () -> 1415926535000L;
     private static BackgroundTaskSchedulerJobService.Clock sZeroClock = () -> 0L;
@@ -196,8 +197,8 @@
 
         return new JobParameters(null /* callback */, taskId, extras, null /* transientExtras */,
                 null /* clipData */, 0 /* clipGrantFlags */, false /* overrideDeadlineExpired */,
-                null /* triggeredContentUris */, null /* triggeredContentAuthorities */,
-                null /* network */);
+                false /* isExpedited */, null /* triggeredContentUris */,
+                null /* triggeredContentAuthorities */, null /* network */);
     }
 
     private static JobParameters buildPeriodicJobParameters(
@@ -221,7 +222,7 @@
 
         return new JobParameters(null /* callback */, taskId, extras, null /* transientExtras */,
                 null /* clipData */, 0 /* clipGrantFlags */, false /* overrideDeadlineExpired */,
-                null /* triggeredContentUris */, null /* triggeredContentAuthorities */,
-                null /* network */);
+                false /* isExpedited */, null /* triggeredContentUris */,
+                null /* triggeredContentAuthorities */, null /* network */);
     }
-}
\ No newline at end of file
+}
diff --git a/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BroadcastReceiverRobolectricTest.java b/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BroadcastReceiverRobolectricTest.java
index ca8b4e04..89d969f 100644
--- a/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BroadcastReceiverRobolectricTest.java
+++ b/components/background_task_scheduler/internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BroadcastReceiverRobolectricTest.java
@@ -11,7 +11,6 @@
 import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.os.BatteryManager;
-import android.os.Build;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -26,7 +25,6 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.components.background_task_scheduler.BackgroundTask;
 import org.chromium.components.background_task_scheduler.BackgroundTaskFactory;
 import org.chromium.components.background_task_scheduler.TaskIds;
@@ -150,7 +148,6 @@
     }
 
     @Test
-    @MinAndroidSdkLevel(Build.VERSION_CODES.M)
     @Feature({"BackgroundTaskScheduler"})
     public void withChargingRequired() throws InterruptedException {
         // Set device in charging mode
@@ -200,7 +197,6 @@
     }
 
     @Test
-    @MinAndroidSdkLevel(Build.VERSION_CODES.L)
     @Feature({"BackgroundTaskScheduler"})
     public void withAnyNetworkRequired() throws InterruptedException {
         mShadowConnectivityManager.setDefaultNetworkActive(true);
@@ -225,7 +221,6 @@
     }
 
     @Test
-    @MinAndroidSdkLevel(Build.VERSION_CODES.M)
     @Feature({"BackgroundTaskScheduler"})
     public void withAnyNetworkRequiredButNoConnectivity() throws InterruptedException {
         mShadowConnectivityManager.setDefaultNetworkActive(false);
diff --git a/components/browser_ui/accessibility/android/BUILD.gn b/components/browser_ui/accessibility/android/BUILD.gn
index 855fc96..8049c4650 100644
--- a/components/browser_ui/accessibility/android/BUILD.gn
+++ b/components/browser_ui/accessibility/android/BUILD.gn
@@ -76,8 +76,7 @@
   ]
 }
 
-java_library("junit") {
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "java/src/org/chromium/components/browser_ui/accessibility/PageZoomMediatorUnitTest.java" ]
 
diff --git a/components/browser_ui/bottomsheet/android/internal/BUILD.gn b/components/browser_ui/bottomsheet/android/internal/BUILD.gn
index 0998eb0..d4b5746a 100644
--- a/components/browser_ui/bottomsheet/android/internal/BUILD.gn
+++ b/components/browser_ui/bottomsheet/android/internal/BUILD.gn
@@ -33,8 +33,7 @@
   resources_package = "org.chromium.components.browser_ui.bottomsheet.internal"
 }
 
-android_library("junit_tests") {
-  bypass_platform_checks = true
+robolectric_library("junit_tests") {
   testonly = true
   sources = [ "java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheetSwipeDetectorTest.java" ]
   deps = [
diff --git a/components/browser_ui/client_certificate/android/BUILD.gn b/components/browser_ui/client_certificate/android/BUILD.gn
index d5f6bfed..7cbfdc2 100644
--- a/components/browser_ui/client_certificate/android/BUILD.gn
+++ b/components/browser_ui/client_certificate/android/BUILD.gn
@@ -46,9 +46,7 @@
   ]
 }
 
-java_library("junit") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "java/src/org/chromium/components/browser_ui/client_certificate/SSLClientCertificateRequestTest.java" ]
   deps = [
diff --git a/components/browser_ui/media/android/BUILD.gn b/components/browser_ui/media/android/BUILD.gn
index 1092df3..84a52dd 100644
--- a/components/browser_ui/media/android/BUILD.gn
+++ b/components/browser_ui/media/android/BUILD.gn
@@ -75,9 +75,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/components/browser_ui/media/MediaImageManagerTest.java",
diff --git a/components/browser_ui/photo_picker/android/BUILD.gn b/components/browser_ui/photo_picker/android/BUILD.gn
index 3a0e1277..b354ddd 100644
--- a/components/browser_ui/photo_picker/android/BUILD.gn
+++ b/components/browser_ui/photo_picker/android/BUILD.gn
@@ -106,9 +106,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/components/browser_ui/photo_picker/FileEnumWorkerTaskTest.java",
diff --git a/components/browser_ui/util/android/BUILD.gn b/components/browser_ui/util/android/BUILD.gn
index 971e6c9..72cc328 100644
--- a/components/browser_ui/util/android/BUILD.gn
+++ b/components/browser_ui/util/android/BUILD.gn
@@ -47,9 +47,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/components/browser_ui/util/BitmapCacheTest.java",
diff --git a/components/browser_ui/webshare/android/BUILD.gn b/components/browser_ui/webshare/android/BUILD.gn
index 018c72a..e6f3510 100644
--- a/components/browser_ui/webshare/android/BUILD.gn
+++ b/components/browser_ui/webshare/android/BUILD.gn
@@ -24,9 +24,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/components/browser_ui/webshare/ShareServiceImplTest.java",
diff --git a/components/browser_ui/widget/android/BUILD.gn b/components/browser_ui/widget/android/BUILD.gn
index 0c28f6f..6cb4638 100644
--- a/components/browser_ui/widget/android/BUILD.gn
+++ b/components/browser_ui/widget/android/BUILD.gn
@@ -378,9 +378,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/components/browser_ui/widget/CompositeTouchDelegateUnitTest.java",
diff --git a/components/content_capture/android/junit/BUILD.gn b/components/content_capture/android/junit/BUILD.gn
index 17337b0ea..f740b50e 100644
--- a/components/content_capture/android/junit/BUILD.gn
+++ b/components/content_capture/android/junit/BUILD.gn
@@ -5,9 +5,7 @@
 import("//build/config/android/config.gni")
 import("//build/config/android/rules.gni")
 
-java_library("components_content_capture_junit_tests") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("components_content_capture_junit_tests") {
   testonly = true
   sources = [
     "src/org/chromium/components/content_capture/PlatformAPIWrapperTest.java",
diff --git a/components/crash/android/BUILD.gn b/components/crash/android/BUILD.gn
index 63a0d91..b7ef049 100644
--- a/components/crash/android/BUILD.gn
+++ b/components/crash/android/BUILD.gn
@@ -52,9 +52,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "junit/src/org/chromium/components/crash/LogcatCrashExtractorTest.java",
diff --git a/components/dom_distiller/content/browser/distiller_page_web_contents.cc b/components/dom_distiller/content/browser/distiller_page_web_contents.cc
index e516b97b..e2b93f4d 100644
--- a/components/dom_distiller/content/browser/distiller_page_web_contents.cc
+++ b/components/dom_distiller/content/browser/distiller_page_web_contents.cc
@@ -150,7 +150,7 @@
     content::RenderFrameHost* render_frame_host,
     const GURL& validated_url,
     int error_code) {
-  if (!render_frame_host->GetParent()) {
+  if (render_frame_host->IsInPrimaryMainFrame()) {
     content::WebContentsObserver::Observe(nullptr);
     DCHECK(state_ == LOADING_PAGE || state_ == EXECUTING_JAVASCRIPT);
     state_ = PAGELOAD_FAILED;
diff --git a/components/download/network/BUILD.gn b/components/download/network/BUILD.gn
index 59904ad6..81df40f6 100644
--- a/components/download/network/BUILD.gn
+++ b/components/download/network/BUILD.gn
@@ -67,7 +67,6 @@
   }
 
   android_library("javatests") {
-    bypass_platform_checks = true
     testonly = true
 
     sources = [ "android/java/src/org/chromium/components/download/NetworkStatusListenerAndroidTest.java" ]
diff --git a/components/embedder_support/android/BUILD.gn b/components/embedder_support/android/BUILD.gn
index 7aa380ab..ab9e8ea 100644
--- a/components/embedder_support/android/BUILD.gn
+++ b/components/embedder_support/android/BUILD.gn
@@ -290,9 +290,7 @@
   sources = [ "native_java_unittests/src/org/chromium/components/embedder_support/util/InputStreamUnittest.java" ]
 }
 
-android_library("junit_test_support") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("junit_test_support") {
   testonly = true
   sources = [ "junit/src/org/chromium/components/embedder_support/util/ShadowUrlUtilities.java" ]
   deps = [
@@ -301,9 +299,7 @@
   ]
 }
 
-java_library("components_embedder_support_junit_tests") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("components_embedder_support_junit_tests") {
   testonly = true
   sources = [
     "junit/src/org/chromium/components/embedder_support/util/OriginTest.java",
diff --git a/components/externalauth/android/BUILD.gn b/components/externalauth/android/BUILD.gn
index b1239f692..6c65f49 100644
--- a/components/externalauth/android/BUILD.gn
+++ b/components/externalauth/android/BUILD.gn
@@ -42,9 +42,7 @@
   ]
 }
 
-android_library("junit") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
 
   deps = [
diff --git a/components/favicon_base/favicon_url_parser.cc b/components/favicon_base/favicon_url_parser.cc
index 2df39ba..ca581692 100644
--- a/components/favicon_base/favicon_url_parser.cc
+++ b/components/favicon_base/favicon_url_parser.cc
@@ -97,20 +97,18 @@
     const base::StringPiece key = it.GetKey();
     // Note: each of these keys can be used in chrome://favicon2 path. See file
     // "favicon_url_parser.h" for a description of what each one does.
-    if (key == "allow_google_server_fallback" ||
-        key == "allowGoogleServerFallback") {
+    if (key == "allowGoogleServerFallback") {
       const std::string val = it.GetUnescapedValue();
       if (!(val == "0" || val == "1"))
         return false;
       parsed->allow_favicon_server_fallback = val == "1";
-    } else if (key == "show_fallback_monogram" ||
-               key == "showFallbackMonogram") {
+    } else if (key == "showFallbackMonogram") {
       parsed->show_fallback_monogram = true;
-    } else if (key == "icon_url" || key == "iconUrl") {
+    } else if (key == "iconUrl") {
       parsed->icon_url = it.GetUnescapedValue();
-    } else if (key == "page_url" || key == "pageUrl") {
+    } else if (key == "pageUrl") {
       parsed->page_url = it.GetUnescapedValue();
-    } else if ((key == "scale_factor" || key == "scaleFactor") &&
+    } else if (key == "scaleFactor" &&
                !webui::ParseScaleFactor(it.GetUnescapedValue(),
                                         &parsed->device_scale_factor)) {
       return false;
diff --git a/components/favicon_base/favicon_url_parser.h b/components/favicon_base/favicon_url_parser.h
index 58c5b297..c8ac448 100644
--- a/components/favicon_base/favicon_url_parser.h
+++ b/components/favicon_base/favicon_url_parser.h
@@ -47,7 +47,7 @@
 // Enum describing the two possible url formats: the legacy chrome://favicon
 // and chrome://favicon2.
 // - chrome://favicon format:
-//   chrome://favicon/size&scalefactor/iconurl/url
+//   chrome://favicon/size&scaleFactor/iconUrl/url
 // Some parameters are optional as described below. However, the order of the
 // parameters is not interchangeable.
 //
@@ -56,7 +56,7 @@
 //    Specifies the page URL of the requested favicon. If the 'iconurl'
 //    parameter is specified, the URL refers to the URL of the favicon image
 //    instead.
-//  'size&scalefactor'  Optional
+//  'size&scaleFactor'  Optional
 //    Values: ['size/aa@bx/']
 //      Specifies the requested favicon's size in DIP (aa) and the requested
 //      favicon's scale factor. (b).
@@ -64,41 +64,41 @@
 //      If the parameter is unspecified, the requested favicon's size defaults
 //      to 16 and the requested scale factor defaults to 1x.
 //      Example: chrome://favicon/size/16@2x/https://www.google.com/
-//  'iconurl'           Optional
-//    Values: ['iconurl']
+//  'iconUrl'           Optional
+//    Values: ['iconUrl']
 //    'iconurl': Specifies that the url parameter refers to the URL of
 //    the favicon image as opposed to the URL of the page that the favicon is
 //    on.
 //    Example: chrome://favicon/iconurl/https://www.google.com/favicon.ico
 //
 // - chrome://favicon2 format:
-//   chrome://favicon2/?query_parameters
+//   chrome://favicon2/?queryParameters
 // Standard URL query parameters are used as described below.
 //
 // URL Parameters:
-//  'page_url'
+//  'pageUrl'
 //    URL pointing to the page whose favicon we want.
-//  'icon_url'
-//    URL pointing directly to favicon image associated with |page_url|.
+//  'iconUrl'
+//    URL pointing directly to favicon image associated with `pageUrl`.
 //    Pointed image will not necessarily have the most appropriate resolution
 //    to the user's device.
 //
-// At least one of the two must be provided and non-empty. If both |page_url|
-// and |icon_url| are passed, |page_url| will have precedence.
+// At least one of the two must be provided and non-empty. If both `pageUrl`
+// and `iconUrl` are passed, `pageUrl` will have precedence.
 //
 // Other parameters:
 //  'size'  Optional
 //      Specifies the requested favicon's size in DIP. If unspecified, defaults
 //      to 16.
 //    Example: chrome://favicon2/?size=32
-// TODO(victorvianna): Refactor to remove scale_factor parameter.
-//  'scale_factor'  Optional
+// TODO(victorvianna): Refactor to remove scaleFactor parameter.
+//  'scaleFactor'  Optional
 //      Values: ['SCALEx']
 //      Specifies the requested favicon's scale factor. If unspecified, defaults
 //      to 1x.
-//    Example: chrome://favicon2/?scale_factor=1.2x
+//    Example: chrome://favicon2/?scaleFactor=1.2x
 //
-//  'allow_google_server_fallback' Optional
+//  'allowGoogleServerFallback' Optional
 //      Values: ['1', '0']
 //      Specifies whether we are allowed to fall back to an external server
 //      request (by page url) in case the icon is not found locally.
diff --git a/components/favicon_base/favicon_url_parser_unittest.cc b/components/favicon_base/favicon_url_parser_unittest.cc
index 42de1dd..15d1a75 100644
--- a/components/favicon_base/favicon_url_parser_unittest.cc
+++ b/components/favicon_base/favicon_url_parser_unittest.cc
@@ -119,26 +119,26 @@
 TEST_F(FaviconUrlParserTest, Favicon2ParsingSizeParam) {
   chrome::ParsedFaviconPath parsed;
 
-  EXPECT_TRUE(chrome::ParseFaviconPath("?size=32&page_url=https%3A%2F%2Fg.com",
+  EXPECT_TRUE(chrome::ParseFaviconPath("?size=32&pageUrl=https%3A%2F%2Fg.com",
                                        chrome::FaviconUrlFormat::kFavicon2,
                                        &parsed));
   EXPECT_EQ(32, parsed.size_in_dip);
 
-  EXPECT_FALSE(
-      chrome::ParseFaviconPath("?size=abc&page_url=https%3A%2F%2Fg.com",
-                               chrome::FaviconUrlFormat::kFavicon2, &parsed));
+  EXPECT_FALSE(chrome::ParseFaviconPath("?size=abc&pageUrl=https%3A%2F%2Fg.com",
+                                        chrome::FaviconUrlFormat::kFavicon2,
+                                        &parsed));
 }
 
 TEST_F(FaviconUrlParserTest, Favicon2ParsingScaleFactorParam) {
   chrome::ParsedFaviconPath parsed;
 
-  EXPECT_TRUE(chrome::ParseFaviconPath(
-      "?scale_factor=2.1x&page_url=https%3A%2F%2Fg.com",
-      chrome::FaviconUrlFormat::kFavicon2, &parsed));
+  EXPECT_TRUE(
+      chrome::ParseFaviconPath("?scaleFactor=2.1x&pageUrl=https%3A%2F%2Fg.com",
+                               chrome::FaviconUrlFormat::kFavicon2, &parsed));
   EXPECT_EQ(2.1f, parsed.device_scale_factor);
 
   EXPECT_FALSE(
-      chrome::ParseFaviconPath("?scale_factor=-1&page_url=https%3A%2F%2Fg.com",
+      chrome::ParseFaviconPath("?scaleFactor=-1&pageUrl=https%3A%2F%2Fg.com",
                                chrome::FaviconUrlFormat::kFavicon2, &parsed));
 }
 
@@ -146,12 +146,12 @@
   chrome::ParsedFaviconPath parsed;
 
   EXPECT_TRUE(
-      chrome::ParseFaviconPath("?icon_url=https%3A%2F%2Fg.com%2Ffavicon.ico",
+      chrome::ParseFaviconPath("?iconUrl=https%3A%2F%2Fg.com%2Ffavicon.ico",
                                chrome::FaviconUrlFormat::kFavicon2, &parsed));
   EXPECT_EQ(parsed.icon_url, "https://g.com/favicon.ico");
   EXPECT_EQ(parsed.page_url, "");
 
-  EXPECT_TRUE(chrome::ParseFaviconPath("?page_url=https%3A%2F%2Fg.com",
+  EXPECT_TRUE(chrome::ParseFaviconPath("?pageUrl=https%3A%2F%2Fg.com",
                                        chrome::FaviconUrlFormat::kFavicon2,
                                        &parsed));
   EXPECT_EQ(parsed.icon_url, "");
@@ -162,20 +162,20 @@
   chrome::ParsedFaviconPath parsed;
 
   EXPECT_FALSE(chrome::ParseFaviconPath(
-      "?allow_google_server_fallback=invalid&page_url=https%"
+      "?allowGoogleServerFallback=invalid&pageUrl=https%"
       "3A%2F%2Fg.com",
       chrome::FaviconUrlFormat::kFavicon2, &parsed));
 
-  EXPECT_TRUE(chrome::ParseFaviconPath(
-      "?allow_google_server_fallback=0&page_url=https%3A%"
-      "2F%2Fg.com",
-      chrome::FaviconUrlFormat::kFavicon2, &parsed));
+  EXPECT_TRUE(
+      chrome::ParseFaviconPath("?allowGoogleServerFallback=0&pageUrl=https%3A%"
+                               "2F%2Fg.com",
+                               chrome::FaviconUrlFormat::kFavicon2, &parsed));
   EXPECT_FALSE(parsed.allow_favicon_server_fallback);
 
-  EXPECT_TRUE(chrome::ParseFaviconPath(
-      "?allow_google_server_fallback=1&page_url=https%3A%"
-      "2F%2Fg.com",
-      chrome::FaviconUrlFormat::kFavicon2, &parsed));
+  EXPECT_TRUE(
+      chrome::ParseFaviconPath("?allowGoogleServerFallback=1&pageUrl=https%3A%"
+                               "2F%2Fg.com",
+                               chrome::FaviconUrlFormat::kFavicon2, &parsed));
   EXPECT_TRUE(parsed.allow_favicon_server_fallback);
 }
 
@@ -183,14 +183,14 @@
   chrome::ParsedFaviconPath parsed;
 
   parsed.show_fallback_monogram = true;
-  EXPECT_TRUE(chrome::ParseFaviconPath("?page_url=https%3A%2F%2Fg.com",
+  EXPECT_TRUE(chrome::ParseFaviconPath("?pageUrl=https%3A%2F%2Fg.com",
                                        chrome::FaviconUrlFormat::kFavicon2,
                                        &parsed));
   EXPECT_FALSE(parsed.show_fallback_monogram);
 
   parsed.show_fallback_monogram = false;
   EXPECT_TRUE(
-      chrome::ParseFaviconPath("?show_fallback_monogram&page_url=https%3A%"
+      chrome::ParseFaviconPath("?showFallbackMonogram&pageUrl=https%3A%"
                                "2F%2Fg.com",
                                chrome::FaviconUrlFormat::kFavicon2, &parsed));
   EXPECT_TRUE(parsed.show_fallback_monogram);
diff --git a/components/gcm_driver/android/BUILD.gn b/components/gcm_driver/android/BUILD.gn
index 4a409b9..d6d2e63 100644
--- a/components/gcm_driver/android/BUILD.gn
+++ b/components/gcm_driver/android/BUILD.gn
@@ -28,9 +28,7 @@
   ]
 }
 
-java_library("components_gcm_driver_junit_tests") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("components_gcm_driver_junit_tests") {
   testonly = true
   sources = [
     "junit/src/org/chromium/components/gcm_driver/GCMMessageTest.java",
diff --git a/components/history/core/browser/history_types.cc b/components/history/core/browser/history_types.cc
index 25fe3c3..36a1ea8 100644
--- a/components/history/core/browser/history_types.cc
+++ b/components/history/core/browser/history_types.cc
@@ -456,6 +456,21 @@
   }
 }
 
+std::string ClusterKeywordData::GetKeywordTypeLabel() const {
+  switch (type) {
+    case kUnknown:
+      return "Unknown";
+    case kEntityCategory:
+      return "EntityCategory";
+    case kEntityAlias:
+      return "EntityAlias";
+    case kEntity:
+      return "Entity";
+    case kSearchTerms:
+      return "SearchTerms";
+  }
+}
+
 Cluster::Cluster() = default;
 Cluster::Cluster(int64_t cluster_id,
                  const std::vector<ClusterVisit>& visits,
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h
index 5f258897..28dcf21f 100644
--- a/components/history/core/browser/history_types.h
+++ b/components/history/core/browser/history_types.h
@@ -884,13 +884,20 @@
 
 // Additional data for a cluster keyword.
 struct ClusterKeywordData {
+  // Corresponds to `HistoryClusterKeywordType` in
+  // tools/metrics/histograms/enums.xml.
+  //
   // Types are ordered according to preferences.
+  //
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
   enum ClusterKeywordType {
     kUnknown = 0,
     kEntityCategory = 1,
     kEntityAlias = 2,
     kEntity = 3,
-    kSearchTerms = 4
+    kSearchTerms = 4,
+    kMaxValue = kSearchTerms
   };
 
   ClusterKeywordData();
@@ -910,6 +917,13 @@
   // type.
   void MaybeUpdateKeywordType(ClusterKeywordType other_type);
 
+  // Returns a keyword type label.
+  // Only used for logging the UMA metric:
+  //   Omnibox.SuggestionUsed.ResumeJourney.ClusterKeywordType.*.CTR.
+  //
+  // crbug.com/1335975: Remove this method when we remove the histograms.
+  std::string GetKeywordTypeLabel() const;
+
   ClusterKeywordType type;
 
   // A floating point score describing how important this
diff --git a/components/history_clusters/core/history_clusters_service.cc b/components/history_clusters/core/history_clusters_service.cc
index c14b6924..e93665a7 100644
--- a/components/history_clusters/core/history_clusters_service.cc
+++ b/components/history_clusters/core/history_clusters_service.cc
@@ -301,12 +301,18 @@
     }
     // Lowercase the keywords for case insensitive matching while adding to the
     // accumulator.
+    // Keep the keyword data with the highest score if found in multiple
+    // clusters.
     if (keyword_accumulator->size() < max_keyword_phrases) {
       for (const auto& keyword_data_p : cluster.keyword_to_data_map) {
         auto keyword = base::i18n::ToLower(keyword_data_p.first);
-        if (keyword_accumulator->find(keyword) == keyword_accumulator->end()) {
+        auto it = keyword_accumulator->find(keyword);
+        if (it == keyword_accumulator->end()) {
           keyword_accumulator->insert(
               std::make_pair(keyword, keyword_data_p.second));
+        } else if (it->second.score < keyword_data_p.second.score) {
+          // Update keyword data to the one with a higher score.
+          it->second = keyword_data_p.second;
         }
       }
     }
diff --git a/components/history_clusters/core/history_clusters_service_unittest.cc b/components/history_clusters/core/history_clusters_service_unittest.cc
index 5d1db35..16730ee 100644
--- a/components/history_clusters/core/history_clusters_service_unittest.cc
+++ b/components/history_clusters/core/history_clusters_service_unittest.cc
@@ -615,17 +615,30 @@
     test_clustering_backend_->WaitForGetClustersCall();
 
     std::vector<history::Cluster> clusters;
-    clusters.push_back(
-        history::Cluster(0,
-                         {
-                             test_clustering_backend_->GetVisitById(5),
-                             test_clustering_backend_->GetVisitById(2),
-                         },
-                         {{u"apples", history::ClusterKeywordData()},
-                          {u"oranges", history::ClusterKeywordData()},
-                          {u"z", history::ClusterKeywordData()},
-                          {u"apples bananas", history::ClusterKeywordData()}},
-                         /*should_show_on_prominent_ui_surfaces=*/true));
+    clusters.push_back(history::Cluster(
+        0,
+        {
+            test_clustering_backend_->GetVisitById(5),
+            test_clustering_backend_->GetVisitById(2),
+        },
+        {{u"apples", history::ClusterKeywordData(
+                         history::ClusterKeywordData::kEntity, 5.0f, {})},
+         {u"oranges", history::ClusterKeywordData()},
+         {u"z", history::ClusterKeywordData()},
+         {u"apples bananas", history::ClusterKeywordData()}},
+        /*should_show_on_prominent_ui_surfaces=*/true));
+    clusters.push_back(history::Cluster(
+        0,
+        {
+            test_clustering_backend_->GetVisitById(5),
+            test_clustering_backend_->GetVisitById(2),
+        },
+        {
+            {u"apples",
+             history::ClusterKeywordData(
+                 history::ClusterKeywordData::kSearchTerms, 100.0f, {})},
+        },
+        /*should_show_on_prominent_ui_surfaces=*/true));
     clusters.push_back(
         history::Cluster(0,
                          {
@@ -661,7 +674,13 @@
   flush_keyword_requests(3);
 
   // Now the exact query should match the populated cache.
-  EXPECT_TRUE(history_clusters_service_->DoesQueryMatchAnyCluster("apples"));
+  const auto keyword_data =
+      history_clusters_service_->DoesQueryMatchAnyCluster("apples");
+  EXPECT_TRUE(keyword_data);
+  // Its keyword data type is kSearchTerms as it has a higher score.
+  EXPECT_EQ(keyword_data,
+            history::ClusterKeywordData(
+                history::ClusterKeywordData::kSearchTerms, 100.0f, {}));
 
   // Check that clusters that shouldn't be shown on prominent UI surfaces don't
   // have their keywords inserted into the keyword bag.
diff --git a/components/image_fetcher/BUILD.gn b/components/image_fetcher/BUILD.gn
index a2aadfb5..0a8282fe 100644
--- a/components/image_fetcher/BUILD.gn
+++ b/components/image_fetcher/BUILD.gn
@@ -50,9 +50,8 @@
   ]
 }
 
-java_library("junit") {
+robolectric_library("junit") {
   testonly = true
-  bypass_platform_checks = true
   sources = [
     "android/junit/src/org/chromium/components/image_fetcher/CachedImageFetcherTest.java",
     "android/junit/src/org/chromium/components/image_fetcher/ImageFetcherBridgeTest.java",
diff --git a/components/installedapp/android/BUILD.gn b/components/installedapp/android/BUILD.gn
index 4203160..ebe98f5 100644
--- a/components/installedapp/android/BUILD.gn
+++ b/components/installedapp/android/BUILD.gn
@@ -63,9 +63,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources =
       [ "java/src/org/chromium/components/installedapp/PackageHashTest.java" ]
diff --git a/components/language/android/BUILD.gn b/components/language/android/BUILD.gn
index 51dfee3..382c9c63 100644
--- a/components/language/android/BUILD.gn
+++ b/components/language/android/BUILD.gn
@@ -67,9 +67,7 @@
   deps = [ ":ulp_delegate_java" ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "java/src/org/chromium/components/language/LanguageProfileControllerUnitTest.java" ]
   deps = [
diff --git a/components/media_router/browser/android/BUILD.gn b/components/media_router/browser/android/BUILD.gn
index 55593264..aa502cf 100644
--- a/components/media_router/browser/android/BUILD.gn
+++ b/components/media_router/browser/android/BUILD.gn
@@ -119,9 +119,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "junit/src/org/chromium/components/media_router/BrowserMediaRouterRouteTest.java",
diff --git a/components/messages/android/BUILD.gn b/components/messages/android/BUILD.gn
index 2617e56..092ef31 100644
--- a/components/messages/android/BUILD.gn
+++ b/components/messages/android/BUILD.gn
@@ -128,9 +128,7 @@
   deps = [ "//base" ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources =
       [ "java/src/org/chromium/components/messages/MessageWrapperTest.java" ]
diff --git a/components/messages/android/internal/BUILD.gn b/components/messages/android/internal/BUILD.gn
index 9a7600f0..d91f9f4 100644
--- a/components/messages/android/internal/BUILD.gn
+++ b/components/messages/android/internal/BUILD.gn
@@ -40,9 +40,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/components/messages/MessageAutoDismissTimerTest.java",
diff --git a/components/omnibox/browser/actions/history_clusters_action.cc b/components/omnibox/browser/actions/history_clusters_action.cc
index d455d93..1e3a6cf5 100644
--- a/components/omnibox/browser/actions/history_clusters_action.cc
+++ b/components/omnibox/browser/actions/history_clusters_action.cc
@@ -52,14 +52,30 @@
       ->relevance;
 }
 
-// Record the entity collection level CTR metric for the journey chip.
-void RecordEntityCollectionCtrForJourney(const std::string& collection_label,
-                                         bool executed) {
-  // Append an entity collection label.
-  std::string uma_metric_name = base::StringPrintf(
-      "Omnibox.SuggestionUsed.ResumeJourney.PageEntityCollection.%s.CTR",
-      collection_label.c_str());
-  base::UmaHistogramBoolean(uma_metric_name, executed);
+// A template function for recording enum metrics for shown and used journey
+// chips as well as their CTR metrics.
+template <class EnumT>
+void RecordShownUsedEnumAndCtrMetrics(const std::string& metric_name,
+                                      EnumT val,
+                                      const std::string& label,
+                                      bool executed) {
+  base::UmaHistogramEnumeration("Omnibox.ResumeJourneyShown." + metric_name,
+                                val);
+  if (executed) {
+    base::UmaHistogramEnumeration(
+        "Omnibox.SuggestionUsed.ResumeJourney." + metric_name, val);
+  }
+
+  // Record the CTR metric.
+  std::string ctr_metric_name =
+      base::StringPrintf("Omnibox.SuggestionUsed.ResumeJourney.%s.%s.CTR",
+                         metric_name.c_str(), label.c_str());
+  base::UmaHistogramBoolean(ctr_metric_name, executed);
+}
+
+// Multiplies a keyword score by 100, and converts it to int.
+int TransformKeywordScoreForUma(float keyword_score) {
+  return static_cast<int>(keyword_score * 100);
 }
 
 }  // namespace
@@ -97,26 +113,33 @@
   base::UmaHistogramBoolean("Omnibox.SuggestionUsed.ResumeJourneyCTR",
                             executed);
 
+  // Record cluster keyword score UMA metrics.
+  base::UmaHistogramCounts1000(
+      "Omnibox.ResumeJourneyShown.ClusterKeywordScore",
+      TransformKeywordScoreForUma(matched_keyword_data_.score));
+  if (executed) {
+    base::UmaHistogramCounts1000(
+        "Omnibox.SuggestionUsed.ResumeJourney.ClusterKeywordScore",
+        TransformKeywordScoreForUma(matched_keyword_data_.score));
+  }
+
+  // Record cluster keyword type UMA metrics.
+  RecordShownUsedEnumAndCtrMetrics<
+      history::ClusterKeywordData::ClusterKeywordType>(
+      "ClusterKeywordType", matched_keyword_data_.type,
+      matched_keyword_data_.GetKeywordTypeLabel(), executed);
+
+  // Record entity collection UMA metrics.
   if (matched_keyword_data_.entity_collections.empty()) {
     return;
   }
-
-  // Record entity collection UMA metrics.
   const auto& collection_str = matched_keyword_data_.entity_collections.front();
   const optimization_guide::PageEntityCollection collection =
       optimization_guide::GetPageEntityCollectionForString(collection_str);
-
-  base::UmaHistogramEnumeration(
-      "Omnibox.ResumeJourneyShown.PageEntityCollection", collection);
-  if (executed) {
-    base::UmaHistogramEnumeration(
-        "Omnibox.SuggestionUsed.ResumeJourney.PageEntityCollection",
-        collection);
-  }
-
   const auto collection_label =
       optimization_guide::GetPageEntityCollectionLabel(collection_str);
-  RecordEntityCollectionCtrForJourney(collection_label, executed);
+  RecordShownUsedEnumAndCtrMetrics<optimization_guide::PageEntityCollection>(
+      "PageEntityCollection", collection, collection_label, executed);
 }
 
 int32_t HistoryClustersAction::GetID() const {
diff --git a/components/omnibox/browser/shortcuts_provider.cc b/components/omnibox/browser/shortcuts_provider.cc
index 0738ac0..47774c3 100644
--- a/components/omnibox/browser/shortcuts_provider.cc
+++ b/components/omnibox/browser/shortcuts_provider.cc
@@ -448,15 +448,27 @@
             !input.prevent_inline_autocomplete() ||
             match.inline_autocompletion.empty();
       }
-    } else if (!match.TryRichAutocompletion(match.contents, match.description,
-                                            input, shortcut.text)) {
-      const size_t inline_autocomplete_offset =
-          URLPrefix::GetInlineAutocompleteOffset(
-              input.text(), fixed_up_input_text, true, match.fill_into_edit);
-      if (inline_autocomplete_offset != std::u16string::npos) {
-        match.inline_autocompletion =
-            match.fill_into_edit.substr(inline_autocomplete_offset);
-        match.SetAllowedToBeDefault(input);
+    } else {
+      // Try rich autocompletion first. For document suggestions,
+      // `match.contents` is the title, while `description` is something like
+      // 'Google Docs' and shouldn't be autocompleted. For all other nav
+      // suggestions, `contents` is the URL and `description` is the title.
+      bool autocompleted =
+          match.type == AutocompleteMatch::Type::DOCUMENT_SUGGESTION
+              ? match.TryRichAutocompletion(u"", match.contents, input,
+                                            shortcut.text)
+              : match.TryRichAutocompletion(match.contents, match.description,
+                                            input, shortcut.text);
+
+      if (!autocompleted) {
+        const size_t inline_autocomplete_offset =
+            URLPrefix::GetInlineAutocompleteOffset(
+                input.text(), fixed_up_input_text, true, match.fill_into_edit);
+        if (inline_autocomplete_offset != std::u16string::npos) {
+          match.inline_autocompletion =
+              match.fill_into_edit.substr(inline_autocomplete_offset);
+          match.SetAllowedToBeDefault(input);
+        }
       }
     }
   }
diff --git a/components/payments/content/android/BUILD.gn b/components/payments/content/android/BUILD.gn
index b6bb4f8..fd27a52 100644
--- a/components/payments/content/android/BUILD.gn
+++ b/components/payments/content/android/BUILD.gn
@@ -309,9 +309,7 @@
   sources = [ "//components/payments/core/journey_logger.h" ]
 }
 
-java_library("junit_test_support") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("junit_test_support") {
   testonly = true
   sources = [
     "junit/src/org/chromium/components/payments/test_support/PaymentRequestServiceBuilder.java",
@@ -335,9 +333,7 @@
   ]
 }
 
-java_library("junit") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java",
diff --git a/components/permissions/android/BUILD.gn b/components/permissions/android/BUILD.gn
index a0711ec..f8e877a 100644
--- a/components/permissions/android/BUILD.gn
+++ b/components/permissions/android/BUILD.gn
@@ -152,9 +152,7 @@
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
 
-android_library("components_permissions_junit_tests") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("components_permissions_junit_tests") {
   testonly = true
   sources = [ "junit/src/org/chromium/components/permissions/nfc/NfcSystemLevelPromptTest.java" ]
   deps = [
diff --git a/components/policy/android/BUILD.gn b/components/policy/android/BUILD.gn
index 8447a8be..c2f1b8c 100644
--- a/components/policy/android/BUILD.gn
+++ b/components/policy/android/BUILD.gn
@@ -59,9 +59,7 @@
   sources = _jni_sources
 }
 
-java_library("components_policy_junit_tests") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("components_policy_junit_tests") {
   testonly = true
   sources = [
     "junit/src/org/chromium/components/policy/AbstractAppRestrictionsProviderTest.java",
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 689d943..992ac93 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -29970,7 +29970,7 @@
       'tags': [],
       'desc': '''Configures support of CORS non-wildcard request headers.
 
-      <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> version 97 introduces support for CORS non-wildcard request headers. When scripts make a cross-origin network request via fetch() and XMLHttpRequest with a script-added Authorization header, the header must be explicitly allowed by the Access-Control-Allow-Headers header in the CORS preflight response. "Explicitly" here means that the wild card symbol "*" doesn't cover the Authorization header. See <ph name="CORS_NON_WILDCARD_REQUEST_HEADERS_FEATURE_URL">https://www.chromestatus.com/feature/5768642492891136</ph> for more detail.
+      <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> version 97 introduces support for CORS non-wildcard request headers. When scripts make a cross-origin network request via fetch() and XMLHttpRequest with a script-added Authorization header, the header must be explicitly allowed by the Access-Control-Allow-Headers header in the CORS preflight response. "Explicitly" here means that the wild card symbol "*" doesn't cover the Authorization header. See <ph name="CORS_NON_WILDCARD_REQUEST_HEADERS_FEATURE_URL">https://chromestatus.com/feature/5742041264816128</ph> for more detail.
 
       If this policy is not set, or set to True, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will support the CORS non-wildcard request headers and behave as described above.
 
diff --git a/components/prefs/android/BUILD.gn b/components/prefs/android/BUILD.gn
index e215748..8be793b 100644
--- a/components/prefs/android/BUILD.gn
+++ b/components/prefs/android/BUILD.gn
@@ -18,9 +18,7 @@
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "java/src/org/chromium/components/prefs/PrefServiceTest.java" ]
   deps = [
diff --git a/components/query_tiles/BUILD.gn b/components/query_tiles/BUILD.gn
index 866d3579..cf02ffa 100644
--- a/components/query_tiles/BUILD.gn
+++ b/components/query_tiles/BUILD.gn
@@ -133,8 +133,7 @@
     ]
   }
 
-  android_library("query_tiles_junit_tests") {
-    bypass_platform_checks = true
+  robolectric_library("query_tiles_junit_tests") {
     testonly = true
     sources = [ "android/java/src/org/chromium/components/query_tiles/TileUmaLoggerTest.java" ]
 
diff --git a/components/safe_browsing/content/browser/safe_browsing_network_context.cc b/components/safe_browsing/content/browser/safe_browsing_network_context.cc
index 43daf77..d54a8f6f 100644
--- a/components/safe_browsing/content/browser/safe_browsing_network_context.cc
+++ b/components/safe_browsing/content/browser/safe_browsing_network_context.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/files/file_util.h"
+#include "base/trace_event/trace_event.h"
 #include "components/safe_browsing/core/common/safebrowsing_constants.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/network_context_client_base.h"
@@ -21,6 +22,10 @@
 #include "services/network/network_context.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 
+#if BUILDFLAG(IS_ANDROID)
+#include "base/android/remove_stale_data.h"
+#endif
+
 namespace safe_browsing {
 
 class SafeBrowsingNetworkContext::SharedURLLoaderFactory
@@ -115,6 +120,8 @@
   ~SharedURLLoaderFactory() override = default;
 
   network::mojom::NetworkContextParamsPtr CreateNetworkContextParams() {
+    TRACE_EVENT0("startup",
+                 "SafeBrowsingNetworkContext::CreateNetworkContextParams");
     DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     network::mojom::NetworkContextParamsPtr network_context_params =
         network_context_params_factory_.Run();
@@ -132,6 +139,18 @@
         base::FilePath::StringType(kSafeBrowsingBaseFilename) + kCookiesFile);
     network_context_params->enable_encrypted_cookies = false;
 
+#if BUILDFLAG(IS_ANDROID)
+    // On Android the `data_directory` was used by some wrong builds instead of
+    // `unsandboxed_data_path`. Cleaning it up. See crbug.com/1331809.
+    // The `cookie_manager` is set by WebView, where the mistaken migration did
+    // not happen.
+    DCHECK(!trigger_migration_);
+    if (!network_context_params->cookie_manager) {
+      base::android::RemoveStaleDataDirectory(
+          network_context_params->file_paths->data_directory.path());
+    }
+#endif  // BUILDFLAG(IS_ANDROID)
+
     return network_context_params;
   }
 
diff --git a/components/segmentation_platform/internal/signals/signal_filter_processor.cc b/components/segmentation_platform/internal/signals/signal_filter_processor.cc
index 32262b0..bb238b97 100644
--- a/components/segmentation_platform/internal/signals/signal_filter_processor.cc
+++ b/components/segmentation_platform/internal/signals/signal_filter_processor.cc
@@ -128,9 +128,15 @@
         std::move(extractor.history_based_segments));
   }
   for (const auto& segment_info : segment_infos) {
+    if (is_first_time_model_update_) {
+      stats::RecordModelUpdateTimeDifference(
+          segment_info->segment_info.segment_id(),
+          segment_info->segment_info.model_update_time_s());
+    }
     storage_service_->signal_storage_config()->OnSignalCollectionStarted(
         segment_info->segment_info.model_metadata());
   }
+  is_first_time_model_update_ = false;
 }
 
 void SignalFilterProcessor::EnableMetrics(bool enable_metrics) {
diff --git a/components/segmentation_platform/internal/signals/signal_filter_processor.h b/components/segmentation_platform/internal/signals/signal_filter_processor.h
index ff39f4c..837fb88 100644
--- a/components/segmentation_platform/internal/signals/signal_filter_processor.h
+++ b/components/segmentation_platform/internal/signals/signal_filter_processor.h
@@ -49,6 +49,9 @@
  private:
   void FilterSignals(DefaultModelManager::SegmentInfoList segment_infos);
 
+  // Boolean to only record metrics the first time models are updated.
+  bool is_first_time_model_update_{true};
+
   const raw_ptr<StorageService> storage_service_;
   const raw_ptr<UserActionSignalHandler> user_action_signal_handler_;
   const raw_ptr<HistogramSignalHandler> histogram_signal_handler_;
diff --git a/components/segmentation_platform/internal/stats.cc b/components/segmentation_platform/internal/stats.cc
index 0bcde99..a4c0f563 100644
--- a/components/segmentation_platform/internal/stats.cc
+++ b/components/segmentation_platform/internal/stats.cc
@@ -316,6 +316,19 @@
   }
 }
 
+void RecordModelUpdateTimeDifference(SegmentId segment_id,
+                                     int64_t model_update_time) {
+  // |model_update_time| might be empty for data persisted before M101.
+  if (model_update_time) {
+    base::Time model_updated_time = base::Time::FromDeltaSinceWindowsEpoch(
+        base::Seconds(model_update_time));
+    base::UmaHistogramCounts1000(
+        "SegmentationPlatform.Init.ModelUpdatedTimeDifferenceInDays." +
+            OptimizationTargetToHistogramVariant(segment_id),
+        (base::Time::Now() - model_updated_time).InDays());
+  }
+}
+
 void RecordSegmentSelectionComputed(
     const std::string& segmentation_key,
     SegmentId new_selection,
diff --git a/components/segmentation_platform/internal/stats.h b/components/segmentation_platform/internal/stats.h
index ac59117d..15fd8c59 100644
--- a/components/segmentation_platform/internal/stats.h
+++ b/components/segmentation_platform/internal/stats.h
@@ -53,6 +53,12 @@
 // Records the score computed for a given segment.
 void RecordModelScore(SegmentId segment_id, float score);
 
+// Records the time difference between when a new version of model from
+// optimization guide is available and when the model is initialized in the
+// client.
+void RecordModelUpdateTimeDifference(SegmentId segment_id,
+                                     int64_t model_update_time);
+
 // Records the result of segment selection whenever segment selection is
 // computed.
 void RecordSegmentSelectionComputed(
diff --git a/components/services/app_service/public/cpp/icon_cache_unittest.cc b/components/services/app_service/public/cpp/icon_cache_unittest.cc
index 4aaad9e..b619172 100644
--- a/components/services/app_service/public/cpp/icon_cache_unittest.cc
+++ b/components/services/app_service/public/cpp/icon_cache_unittest.cc
@@ -13,8 +13,7 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image_skia_rep.h"
 
-class AppsIconCacheTest : public testing::Test,
-                          public ::testing::WithParamInterface<bool> {
+class AppsIconCacheTest : public testing::Test {
  protected:
   enum class HitOrMiss {
     kHit,
@@ -54,49 +53,21 @@
       return nullptr;
     }
 
-    std::unique_ptr<Releaser> LoadIconFromIconKey(
-        apps::mojom::AppType app_type,
-        const std::string& app_id,
-        apps::mojom::IconKeyPtr mojom_icon_key,
-        apps::mojom::IconType icon_type,
-        int32_t size_hint_in_dip,
-        bool allow_placeholder_icon,
-        apps::mojom::Publisher::LoadIconCallback callback) override {
-      auto icon_key = apps::ConvertMojomIconKeyToIconKey(mojom_icon_key);
-      return LoadIconFromIconKey(
-          apps::ConvertMojomAppTypToAppType(app_type), app_id, *icon_key,
-          apps::ConvertMojomIconTypeToIconType(icon_type), size_hint_in_dip,
-          allow_placeholder_icon,
-          apps::IconValueToMojomIconValueCallback(std::move(callback)));
-    }
-
     int num_load_calls_ = 0;
     bool return_placeholder_icons_ = false;
   };
 
-  bool IsLoadIconWithoutMojomEnabled() const { return GetParam(); }
-
   UniqueReleaser LoadIcon(apps::IconLoader* loader,
                           FakeIconLoader* fake,
                           const std::string& app_id,
                           HitOrMiss expect_hom,
                           bool allow_placeholder_icon = false) {
-    static constexpr int32_t size_hint_in_dip = 1;
-
     int before = fake->NumLoadIconFromIconKeyCalls();
 
     UniqueReleaser releaser;
-    if (IsLoadIconWithoutMojomEnabled()) {
-      static constexpr auto app_type = apps::AppType::kWeb;
-      static constexpr auto icon_type = apps::IconType::kUncompressed;
-      releaser = loader->LoadIcon(app_type, app_id, icon_type, size_hint_in_dip,
-                                  allow_placeholder_icon, base::DoNothing());
-    } else {
-      static constexpr auto app_type = apps::mojom::AppType::kWeb;
-      static constexpr auto icon_type = apps::mojom::IconType::kUncompressed;
-      releaser = loader->LoadIcon(app_type, app_id, icon_type, size_hint_in_dip,
-                                  allow_placeholder_icon, base::DoNothing());
-    }
+    releaser = loader->LoadIcon(
+        apps::AppType::kWeb, app_id, apps::IconType::kUncompressed,
+        /*size_hint_in_dip=*/1, allow_placeholder_icon, base::DoNothing());
 
     int after = fake->NumLoadIconFromIconKeyCalls();
     HitOrMiss actual_hom = (after == before) ? kHit : kMiss;
@@ -234,7 +205,7 @@
   }
 };
 
-TEST_P(AppsIconCacheTest, Eager) {
+TEST_F(AppsIconCacheTest, Eager) {
   static constexpr apps::IconCache::GarbageCollectionPolicy gc_policy =
       apps::IconCache::GarbageCollectionPolicy::kEager;
 
@@ -243,7 +214,7 @@
   TestAfterZeroRefcount(gc_policy);
 }
 
-TEST_P(AppsIconCacheTest, ExplicitSweepReleasedIcons) {
+TEST_F(AppsIconCacheTest, ExplicitSweepReleasedIcons) {
   static constexpr apps::IconCache::GarbageCollectionPolicy gc_policy =
       apps::IconCache::GarbageCollectionPolicy::kExplicit;
 
@@ -252,7 +223,7 @@
   TestAfterZeroRefcount(gc_policy);
 }
 
-TEST_P(AppsIconCacheTest, ExplicitRemoveIcons) {
+TEST_F(AppsIconCacheTest, ExplicitRemoveIcons) {
   static constexpr apps::IconCache::GarbageCollectionPolicy gc_policy =
       apps::IconCache::GarbageCollectionPolicy::kExplicit;
 
@@ -260,9 +231,3 @@
   TestPlaceholder(gc_policy);
   TestAfterZeroRefcount(gc_policy, true /* remove_icon */);
 }
-
-// The parameter indicates whether the kAppServiceLoadIconWithoutMojom feature
-// is enabled.
-INSTANTIATE_TEST_SUITE_P(All,
-                         AppsIconCacheTest,
-                         ::testing::Values(true, false));
\ No newline at end of file
diff --git a/components/services/app_service/public/cpp/icon_coalescer_unittest.cc b/components/services/app_service/public/cpp/icon_coalescer_unittest.cc
index 9f00ffc..ec752c3d 100644
--- a/components/services/app_service/public/cpp/icon_coalescer_unittest.cc
+++ b/components/services/app_service/public/cpp/icon_coalescer_unittest.cc
@@ -11,8 +11,7 @@
 #include "components/services/app_service/public/cpp/icon_types.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-class AppsIconCoalescerTest : public testing::Test,
-                              public ::testing::WithParamInterface<bool> {
+class AppsIconCoalescerTest : public testing::Test {
  protected:
   using UniqueReleaser = std::unique_ptr<apps::IconLoader::Releaser>;
 
@@ -64,22 +63,6 @@
                                   weak_ptr_factory_.GetWeakPtr()));
     }
 
-    std::unique_ptr<Releaser> LoadIconFromIconKey(
-        apps::mojom::AppType app_type,
-        const std::string& app_id,
-        apps::mojom::IconKeyPtr mojom_icon_key,
-        apps::mojom::IconType icon_type,
-        int32_t size_hint_in_dip,
-        bool allow_placeholder_icon,
-        apps::mojom::Publisher::LoadIconCallback callback) override {
-      auto icon_key = apps::ConvertMojomIconKeyToIconKey(mojom_icon_key);
-      return LoadIconFromIconKey(
-          apps::ConvertMojomAppTypToAppType(app_type), app_id, *icon_key,
-          apps::ConvertMojomIconTypeToIconType(icon_type), size_hint_in_dip,
-          allow_placeholder_icon,
-          apps::IconValueToMojomIconValueCallback(std::move(callback)));
-    }
-
     apps::IconValuePtr NewIconValuePtr() {
       auto iv = std::make_unique<apps::IconValue>();
       iv->icon_type = apps::IconType::kUncompressed;
@@ -100,38 +83,20 @@
     base::WeakPtrFactory<FakeIconLoader> weak_ptr_factory_{this};
   };
 
-  bool IsLoadIconWithoutMojomEnabled() const { return GetParam(); }
-
   UniqueReleaser LoadIcon(apps::IconLoader* loader,
                           const std::string& app_id,
                           int* counter,
                           int delta) {
-    static constexpr int32_t size_hint_in_dip = 1;
-    static constexpr bool allow_placeholder_icon = false;
-
-    if (IsLoadIconWithoutMojomEnabled()) {
-      static constexpr auto app_type = apps::AppType::kWeb;
-      static constexpr auto icon_type = apps::IconType::kUncompressed;
-      return loader->LoadIcon(
-          app_type, app_id, icon_type, size_hint_in_dip, allow_placeholder_icon,
-          base::BindOnce([](int* counter, int delta,
-                            apps::IconValuePtr icon) { *counter += delta; },
-                         counter, delta));
-    } else {
-      static constexpr auto app_type = apps::mojom::AppType::kWeb;
-      static constexpr auto icon_type = apps::mojom::IconType::kUncompressed;
-      return loader->LoadIcon(
-          app_type, app_id, icon_type, size_hint_in_dip, allow_placeholder_icon,
-          base::BindOnce(
-              [](int* counter, int delta, apps::mojom::IconValuePtr icon) {
-                *counter += delta;
-              },
-              counter, delta));
-    }
+    return loader->LoadIcon(
+        apps::AppType::kWeb, app_id, apps::IconType::kUncompressed,
+        /*size_hint_in_dip=*/1, /*allow_placeholder_icon=*/false,
+        base::BindOnce([](int* counter, int delta,
+                          apps::IconValuePtr icon) { *counter += delta; },
+                       counter, delta));
   }
 };
 
-TEST_P(AppsIconCoalescerTest, CallBackImmediately) {
+TEST_F(AppsIconCoalescerTest, CallBackImmediately) {
   FakeIconLoader fake;
   fake.SetCallBackImmediately(true);
   apps::IconCoalescer coalescer(&fake);
@@ -150,7 +115,7 @@
   EXPECT_EQ(0, fake.NumPendingReleases());
 }
 
-TEST_P(AppsIconCoalescerTest, CallBackDelayedAndAfterRelease) {
+TEST_F(AppsIconCoalescerTest, CallBackDelayedAndAfterRelease) {
   FakeIconLoader fake;
   apps::IconCoalescer coalescer(&fake);
   int counter = 0;
@@ -176,7 +141,7 @@
   EXPECT_EQ(0, fake.NumPendingReleases());
 }
 
-TEST_P(AppsIconCoalescerTest, CallBackDelayedAndBeforeRelease) {
+TEST_F(AppsIconCoalescerTest, CallBackDelayedAndBeforeRelease) {
   FakeIconLoader fake;
   apps::IconCoalescer coalescer(&fake);
   int counter = 0;
@@ -205,7 +170,7 @@
   EXPECT_EQ(0, fake.NumPendingReleases());
 }
 
-TEST_P(AppsIconCoalescerTest, MultipleAppIDs) {
+TEST_F(AppsIconCoalescerTest, MultipleAppIDs) {
   FakeIconLoader fake;
   apps::IconCoalescer coalescer(&fake);
   int ant_counter = 0;
@@ -358,9 +323,3 @@
   e4.reset();
   EXPECT_EQ(0, fake.NumPendingReleases());
 }
-
-// The parameter indicates whether the kAppServiceLoadIconWithoutMojom feature
-// is enabled.
-INSTANTIATE_TEST_SUITE_P(All,
-                         AppsIconCoalescerTest,
-                         ::testing::Values(true, false));
diff --git a/components/services/app_service/public/cpp/icon_loader.cc b/components/services/app_service/public/cpp/icon_loader.cc
index 42743a5..c234643 100644
--- a/components/services/app_service/public/cpp/icon_loader.cc
+++ b/components/services/app_service/public/cpp/icon_loader.cc
@@ -86,6 +86,17 @@
                              std::move(callback));
 }
 
+std::unique_ptr<IconLoader::Releaser> IconLoader::LoadIconFromIconKey(
+    apps::mojom::AppType app_type,
+    const std::string& app_id,
+    apps::mojom::IconKeyPtr icon_key,
+    apps::mojom::IconType icon_type,
+    int32_t size_hint_in_dip,
+    bool allow_placeholder_icon,
+    apps::mojom::Publisher::LoadIconCallback callback) {
+  return nullptr;
+}
+
 std::unique_ptr<IconLoader::Releaser> IconLoader::LoadIcon(
     apps::mojom::AppType app_type,
     const std::string& app_id,
diff --git a/components/services/app_service/public/cpp/icon_loader.h b/components/services/app_service/public/cpp/icon_loader.h
index 37f7e89..a8659c2f 100644
--- a/components/services/app_service/public/cpp/icon_loader.h
+++ b/components/services/app_service/public/cpp/icon_loader.h
@@ -90,7 +90,7 @@
       apps::mojom::IconType icon_type,
       int32_t size_hint_in_dip,
       bool allow_placeholder_icon,
-      apps::mojom::Publisher::LoadIconCallback callback) = 0;
+      apps::mojom::Publisher::LoadIconCallback callback);
 
   // Convenience method that calls "LoadIconFromIconKey(app_type, app_id,
   // GetIconKey(app_id), etc)".
diff --git a/components/signin/public/android/BUILD.gn b/components/signin/public/android/BUILD.gn
index 17bfae08..464c819 100644
--- a/components/signin/public/android/BUILD.gn
+++ b/components/signin/public/android/BUILD.gn
@@ -148,8 +148,7 @@
   ]
 }
 
-java_library("junit") {
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "junit/src/org/chromium/components/signin/AccountManagerFacadeImplTest.java",
diff --git a/components/subresource_filter/android/BUILD.gn b/components/subresource_filter/android/BUILD.gn
index 1f44b7c..b532eadb 100644
--- a/components/subresource_filter/android/BUILD.gn
+++ b/components/subresource_filter/android/BUILD.gn
@@ -34,9 +34,7 @@
   resources_package = "org.chromium.components.subresource_filter"
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [ "java/src/org/chromium/components/subresource_filter/AdsBlockedDialogTest.java" ]
 
diff --git a/components/translate/content/android/BUILD.gn b/components/translate/content/android/BUILD.gn
index 2f4055b5..ed3843ca 100644
--- a/components/translate/content/android/BUILD.gn
+++ b/components/translate/content/android/BUILD.gn
@@ -95,13 +95,18 @@
   srcjar_deps = [ ":translate_android_enums" ]
 }
 
-android_library("javatests") {
+java_library("junit") {
+  # Skip platform checks since Robolectric depends on requires_android targets.
+  bypass_platform_checks = true
   testonly = true
+
   sources =
       [ "java/src/org/chromium/components/translate/TranslateOptionsTest.java" ]
   deps = [
     ":java",
     "//base:base_java_test_support",
+    "//base:base_junit_test_support",
+    "//third_party/android_deps:robolectric_all_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
diff --git a/components/translate/content/android/java/src/org/chromium/components/translate/TranslateOptionsTest.java b/components/translate/content/android/java/src/org/chromium/components/translate/TranslateOptionsTest.java
index ec0b2ea..4a01482 100644
--- a/components/translate/content/android/java/src/org/chromium/components/translate/TranslateOptionsTest.java
+++ b/components/translate/content/android/java/src/org/chromium/components/translate/TranslateOptionsTest.java
@@ -10,16 +10,16 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
 
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.util.Batch;
+import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Feature;
 
 /**
  * Test for TranslateOptions.
  */
-@RunWith(BaseJUnit4ClassRunner.class)
-@Batch(Batch.UNIT_TESTS)
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
 public class TranslateOptionsTest {
     private static final boolean NEVER_LANGUAGE = false;
     private static final boolean NEVER_DOMAIN = false;
diff --git a/components/url_formatter/spoof_checks/top_domains/domains.list b/components/url_formatter/spoof_checks/top_domains/domains.list
index 173141a..22095161 100644
--- a/components/url_formatter/spoof_checks/top_domains/domains.list
+++ b/components/url_formatter/spoof_checks/top_domains/domains.list
@@ -137,7 +137,6 @@
 fandango.com
 fandom.com
 fast.com
-fazenda.gov.br
 fc2.com
 fedex.com
 filmweb.pl
@@ -259,7 +258,6 @@
 linkedin.com
 live.com
 livedoor.com
-livedoor.jp
 livejournal.com
 livescore.com
 livestrong.com
@@ -297,7 +295,6 @@
 n11.com
 namu.wiki
 naver.com
-naver.jp
 nba.com
 nbcnews.com
 nbcsports.com
@@ -330,7 +327,6 @@
 orange.fr
 otto.de
 otvfoco.com.br
-otzovik.com
 over-blog.com
 pantip.com
 passeidireto.com
@@ -371,7 +367,6 @@
 samsung.com
 sanook.com
 sarkariresult.com
-savefrom.net
 sciencedirect.com
 scribd.com
 sfgate.com
@@ -476,7 +471,6 @@
 xnxx2.pro
 xozilla.com
 xvideos.com
-y2mate.com
 yahoo.co.jp
 yahoo.com
 yandex.ru
diff --git a/components/url_formatter/spoof_checks/top_domains/domains.skeletons b/components/url_formatter/spoof_checks/top_domains/domains.skeletons
index b673ba7e..1ca33cd 100644
--- a/components/url_formatter/spoof_checks/top_domains/domains.skeletons
+++ b/components/url_formatter/spoof_checks/top_domains/domains.skeletons
@@ -157,7 +157,6 @@
 fandango.corn, fandangocorn, fandango.com
 fandorn.corn, fandorncorn, fandom.com
 fast.corn, fastcorn, fast.com
-fazenda.gov.br, fazendagovbr, fazenda.gov.br
 fc2.corn, fc2corn, fc2.com
 fedex.corn, fedexcorn, fedex.com
 filrnweb.pl, filrnwebpl, filmweb.pl
@@ -279,7 +278,6 @@
 linkedin.corn, linkedincorn, linkedin.com
 live.corn, livecorn, live.com
 livedoor.corn, livedoorcorn, livedoor.com
-livedoor.jp, livedoorjp, livedoor.jp
 livejournal.corn, livejournalcorn, livejournal.com
 livescore.corn, livescorecorn, livescore.com
 livestrong.corn, livestrongcorn, livestrong.com
@@ -317,7 +315,6 @@
 nll.corn, nllcorn, n11.com
 narnu.wiki, narnuwiki, namu.wiki
 naver.corn, navercorn, naver.com
-naver.jp, naverjp, naver.jp
 nba.corn, nbacorn, nba.com
 nbcnews.corn, nbcnewscorn, nbcnews.com
 nbcsports.corn, nbcsportscorn, nbcsports.com
@@ -350,7 +347,6 @@
 orange.fr, orangefr, orange.fr
 otto.de, ottode, otto.de
 otvfoco.corn.br, otvfococornbr, otvfoco.com.br
-otzovik.corn, otzovikcorn, otzovik.com
 over-blog.corn, overblogcorn, over-blog.com
 pantip.corn, pantipcorn, pantip.com
 passeidireto.corn, passeidiretocorn, passeidireto.com
@@ -391,7 +387,6 @@
 sarnsung.corn, sarnsungcorn, samsung.com
 sanook.corn, sanookcorn, sanook.com
 sarkariresult.corn, sarkariresultcorn, sarkariresult.com
-savefrorn.net, savefrornnet, savefrom.net
 sciencedirect.corn, sciencedirectcorn, sciencedirect.com
 scribd.corn, scribdcorn, scribd.com
 sfgate.corn, sfgatecorn, sfgate.com
@@ -496,7 +491,6 @@
 xnxx2.pro, xnxx2pro, xnxx2.pro
 xozilla.corn, xozillacorn, xozilla.com
 xvideos.corn, xvideoscorn, xvideos.com
-y2rnate.corn, y2rnatecorn, y2mate.com
 yahoo.co.jp, yahoocojp, yahoo.co.jp
 yahoo.corn, yahoocorn, yahoo.com
 yandex.ru, yandexru, yandex.ru
diff --git a/components/variations/android/BUILD.gn b/components/variations/android/BUILD.gn
index fb1996d..08335bfc 100644
--- a/components/variations/android/BUILD.gn
+++ b/components/variations/android/BUILD.gn
@@ -24,9 +24,7 @@
   ]
 }
 
-java_library("components_variations_junit_tests") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("components_variations_junit_tests") {
   testonly = true
   sources = [
     "junit/src/org/chromium/components/variations/VariationsCompressionUtilsTest.java",
diff --git a/components/webapk/android/libs/client/BUILD.gn b/components/webapk/android/libs/client/BUILD.gn
index cee049d..894ea07 100644
--- a/components/webapk/android/libs/client/BUILD.gn
+++ b/components/webapk/android/libs/client/BUILD.gn
@@ -17,9 +17,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "src/org/chromium/components/webapk/lib/client/WebApkValidatorTest.java",
diff --git a/components/webapps/browser/android/BUILD.gn b/components/webapps/browser/android/BUILD.gn
index 9a5de41..6c325d81 100644
--- a/components/webapps/browser/android/BUILD.gn
+++ b/components/webapps/browser/android/BUILD.gn
@@ -161,9 +161,7 @@
   ]
 }
 
-java_library("junit") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("junit") {
   testonly = true
   sources = [
     "java/src/org/chromium/components/webapps/AddToHomescreenDialogViewTest.java",
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc
index a6d83a6..7d9289f8 100644
--- a/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -944,7 +944,7 @@
   ASSERT_TRUE(NavigateToURL(shell(), html_data_url));
   // TODO(https://crbug.com/1332468): Investigate why this does not return
   // true.
-  std::ignore = waiter.WaitForNotification();
+  ASSERT_TRUE(waiter.WaitForNotification());
 
   // Check that at least the root of the page has indeed loaded and that it is
   // focused.
@@ -1171,7 +1171,7 @@
   WaitForAccessibilityFocusChange();
   // TODO(https://crbug.com/1332468): Investigate why this does not return
   // true.
-  std::ignore = waiter.WaitForNotification();
+  ASSERT_TRUE(waiter.WaitForNotification());
 
   Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
   ASSERT_TRUE(document);
diff --git a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 482288ba..a17b8f37 100644
--- a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -121,7 +121,7 @@
         NavigateToURL(shell(), embedded_test_server()->GetURL(html_file_path)));
     // TODO(https://crbug.com/1332468): Investigate why this does not return
     // true.
-    std::ignore = waiter.WaitForNotification();
+    ASSERT_TRUE(waiter.WaitForNotification());
   }
 
   BrowserAccessibilityManager* GetManager() const {
diff --git a/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index 890b170..63e912c 100644
--- a/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -347,7 +347,7 @@
     EXPECT_TRUE(NavigateToURL(shell(), url));
     // TODO(https://crbug.com/1332468): Investigate why this does not return
     // true.
-    std::ignore = accessibility_waiter.WaitForNotification();
+    ASSERT_TRUE(accessibility_waiter.WaitForNotification());
   }
 
   WaitForAllFramesLoaded();
@@ -551,7 +551,7 @@
   // when |event_recorder| records a platform event.
   // TODO(https://crbug.com/1332468): Investigate why this does not return
   // true.
-  std::ignore = waiter.WaitForNotification();
+  EXPECT_TRUE(waiter.WaitForNotification());
 
   // More than one accessibility event could have been generated.
   // To make sure we've received all accessibility events, add a
diff --git a/content/browser/accessibility/hit_testing_browsertest.cc b/content/browser/accessibility/hit_testing_browsertest.cc
index 410f373..5193d191 100644
--- a/content/browser/accessibility/hit_testing_browsertest.cc
+++ b/content/browser/accessibility/hit_testing_browsertest.cc
@@ -262,7 +262,7 @@
 
   // Ensure we get an accessibility update reflecting the new scale factor.
   // TODO(https://crbug.com/1332468): Investigate why this does not return true.
-  std::ignore = accessibility_waiter.WaitForNotification();
+  ASSERT_TRUE(accessibility_waiter.WaitForNotification());
 }
 
 std::string
@@ -658,7 +658,7 @@
   SynchronizeThreads();
   // TODO(https://crbug.com/1332468): Investigate why this does not return
   // true.
-  std::ignore = waiter.WaitForNotification();
+  ASSERT_TRUE(waiter.WaitForNotification());
 
   WaitForAccessibilityTreeToContainNodeWithName(shell()->web_contents(),
                                                 "rectA");
@@ -707,7 +707,7 @@
   SynchronizeThreads();
   // TODO(https://crbug.com/1332468): Investigate why this does not return
   // true.
-  std::ignore = waiter.WaitForNotification();
+  ASSERT_TRUE(waiter.WaitForNotification());
 
   WaitForAccessibilityTreeToContainNodeWithName(shell()->web_contents(),
                                                 "rectA");
@@ -857,7 +857,7 @@
   EXPECT_TRUE(NavigateToURL(shell(), url));
   SynchronizeThreads();
   // TODO(https://crbug.com/1332468): Investigate why this does not return true.
-  std::ignore = waiter.WaitForNotification();
+  ASSERT_TRUE(waiter.WaitForNotification());
 
   WaitForAccessibilityTreeToContainNodeWithName(shell()->web_contents(),
                                                 "Dial");
diff --git a/content/browser/accessibility/touch_accessibility_aura_browsertest.cc b/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
index d6d5ffd22..c4625e6 100644
--- a/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
+++ b/content/browser/accessibility/touch_accessibility_aura_browsertest.cc
@@ -49,7 +49,7 @@
     EXPECT_TRUE(NavigateToURL(shell(), url));
     // TODO(https://crbug.com/1332468): Investigate why this does not return
     // true.
-    std::ignore = waiter.WaitForNotification();
+    ASSERT_TRUE(waiter.WaitForNotification());
   }
 
   void SendTouchExplorationEvent(int x, int y) {
diff --git a/content/browser/portal/portal_browsertest.cc b/content/browser/portal/portal_browsertest.cc
index 6001df4..2c6a3acf 100644
--- a/content/browser/portal/portal_browsertest.cc
+++ b/content/browser/portal/portal_browsertest.cc
@@ -2130,7 +2130,7 @@
     adoption_observer.WaitUntilPortalCreated();
     // TODO(https://crbug.com/1332461): Investigate why this does not return
     // true.
-    std::ignore = waiter.WaitForNotification();
+    ASSERT_TRUE(waiter.WaitForNotification());
   }
   EXPECT_EQ(0, main_frame->accessibility_fatal_error_count_for_testing());
 }
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc
index 01a85ef..07c28ac3 100644
--- a/content/browser/webid/idp_network_request_manager.cc
+++ b/content/browser/webid/idp_network_request_manager.cc
@@ -95,10 +95,6 @@
 // response size that is a part of this protocol.
 constexpr int maxResponseSizeInKiB = 1024;
 
-// safe_zone_diameter/icon_size as defined in
-// https://www.w3.org/TR/appmanifest/#icon-masks
-constexpr float kMaskableWebIconSafeZoneRatio = 0.8f;
-
 net::NetworkTrafficAnnotationTag CreateTrafficAnnotation() {
   return net::DefineNetworkTrafficAnnotation("fedcm", R"(
         semantics {
@@ -299,19 +295,10 @@
     }
 
     if (brand_icon_minimum_size && brand_icon_ideal_size) {
-      // As only a single bitmap is selected, select a bitmap which works with
-      // a high density display (if the OS supports high density displays).
-      float max_supported_scale = ui::GetScaleForResourceScaleFactor(
-          ui::GetSupportedResourceScaleFactors().back());
-      int minimum_icon_size_px = brand_icon_minimum_size.value() *
-                                 max_supported_scale /
-                                 kMaskableWebIconSafeZoneRatio;
-      int ideal_icon_size_px = brand_icon_ideal_size.value() *
-                               max_supported_scale /
-                               kMaskableWebIconSafeZoneRatio;
       idp_metadata.brand_icon_url =
           blink::ManifestIconSelector::FindBestMatchingSquareIcon(
-              icons, ideal_icon_size_px, minimum_icon_size_px,
+              icons, brand_icon_ideal_size.value(),
+              brand_icon_minimum_size.value(),
               blink::mojom::ManifestImageResource_Purpose::MASKABLE);
     }
   }
diff --git a/content/browser/webid/idp_network_request_manager_unittest.cc b/content/browser/webid/idp_network_request_manager_unittest.cc
index ac5b949d..bca6d17 100644
--- a/content/browser/webid/idp_network_request_manager_unittest.cc
+++ b/content/browser/webid/idp_network_request_manager_unittest.cc
@@ -21,7 +21,6 @@
 #include "services/network/public/mojom/client_security_state.mojom.h"
 #include "services/network/test/test_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/layout.h"
 #include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
 
@@ -577,10 +576,6 @@
 }
 
 TEST_F(IdpNetworkRequestManagerTest, ParseManifestBrandingSelectBestSize) {
-  // Selected icon depends on OS supported scale factors.
-  ui::test::ScopedSetSupportedResourceScaleFactors
-      scoped_supported_scale_factors({ui::k100Percent});
-
   const char test_json[] = R"({
   "branding" : {
     "icons": [
@@ -593,23 +588,22 @@
         "size": 16
       },
       {
-        "url": "https://example.com/39.png",
-        "size": 39
+        "url": "https://example.com/31.png",
+        "size": 31
       },
       {
-        "url": "https://example.com/40.png",
-        "size": 40
+        "url": "https://example.com/32.png",
+        "size": 32
       },
       {
-        "url": "https://example.com/41.png",
-        "size": 41
+        "url": "https://example.com/33.png",
+        "size": 33
       }
     ]
   }
   })";
 
   ASSERT_EQ(32, kTestIdpBrandIconIdealSize);
-  // 32 / kMaskableWebIconSafeZoneRatio = 40
 
   FetchStatus fetch_status;
   IdentityProviderMetadata idp_metadata;
@@ -617,7 +611,56 @@
       SendManifestRequestAndWaitForResponse(test_json);
 
   EXPECT_EQ(FetchStatus::kSuccess, fetch_status);
-  EXPECT_EQ("https://example.com/40.png", idp_metadata.brand_icon_url.spec());
+  EXPECT_EQ("https://example.com/32.png", idp_metadata.brand_icon_url.spec());
+}
+
+// Test that the icon is rejected if there is an explicit brand icon size in the
+// manifest and it is smaller than the `idp_brand_icon_minimum_size` parameter
+// passed to IdpNetworkRequestManager::FetchManifest().
+TEST_F(IdpNetworkRequestManagerTest, ParseManifestBrandingMinSize) {
+  ASSERT_EQ(16, kTestIdpBrandIconMinimumSize);
+
+  {
+    const char test_json[] = R"({
+    "branding" : {
+      "icons": [
+        {
+          "url": "https://example.com/15.png",
+          "size": 15
+        }
+      ]
+    }
+    })";
+
+    FetchStatus fetch_status;
+    IdentityProviderMetadata idp_metadata;
+    std::tie(fetch_status, idp_metadata) =
+        SendManifestRequestAndWaitForResponse(test_json);
+
+    EXPECT_EQ(FetchStatus::kSuccess, fetch_status);
+    EXPECT_EQ(GURL(), idp_metadata.brand_icon_url);
+  }
+
+  {
+    const char test_json[] = R"({
+    "branding" : {
+      "icons": [
+        {
+          "url": "https://example.com/16.png",
+          "size": 16
+        }
+      ]
+    }
+    })";
+
+    FetchStatus fetch_status;
+    IdentityProviderMetadata idp_metadata;
+    std::tie(fetch_status, idp_metadata) =
+        SendManifestRequestAndWaitForResponse(test_json);
+
+    EXPECT_EQ(FetchStatus::kSuccess, fetch_status);
+    EXPECT_EQ("https://example.com/16.png", idp_metadata.brand_icon_url.spec());
+  }
 }
 
 // Tests that we send the correct referrer for account requests.
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index fb7e6f51..ca8e62e 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -640,6 +640,7 @@
     "junit/src/org/chromium/content/browser/sms/SmsProviderGmsTest.java",
     "junit/src/org/chromium/content_public/browser/MessagePayloadTest.java",
   ]
+
   deps = [
     ":content_java",
     "//base:base_java",
@@ -656,9 +657,10 @@
     "//third_party/androidx:androidx_test_runner_java",
     "//third_party/blink/public/mojom:android_mojo_bindings_java",
     "//third_party/hamcrest:hamcrest_java",
+    "//third_party/junit",
+    "//third_party/mockito:mockito_java",
     "//ui/android:ui_java",
     "//ui/gfx/geometry/mojom:mojom_java",
   ]
-
   data_deps = [ "//testing/buildbot/filters:content_junit_tests_filters" ]
 }
diff --git a/content/public/test/accessibility_notification_waiter.cc b/content/public/test/accessibility_notification_waiter.cc
index 61ae657..f6bada4 100644
--- a/content/public/test/accessibility_notification_waiter.cc
+++ b/content/public/test/accessibility_notification_waiter.cc
@@ -115,14 +115,17 @@
 }
 
 bool AccessibilityNotificationWaiter::WaitForNotification() {
-  notification_received_ = false;
   loop_runner_->Run();
 
+  bool notification_received = notification_received_;
+  // Reset everything to allow reuse.
   // Each loop runner can only be called once. Create a new one in case
   // the caller wants to call this again to wait for the next notification.
   loop_runner_ = std::make_unique<base::RunLoop>();
   loop_runner_quit_closure_ = loop_runner_->QuitClosure();
-  return notification_received_;
+  notification_received_ = false;
+
+  return notification_received;
 }
 
 bool AccessibilityNotificationWaiter::WaitForNotificationWithTimeout(
diff --git a/content/test/data/gpu/vc/webgpu_video.js b/content/test/data/gpu/vc/webgpu_video.js
index ea1a6e4..1e34ff0 100644
--- a/content/test/data/gpu/vc/webgpu_video.js
+++ b/content/test/data/gpu/vc/webgpu_video.js
@@ -545,13 +545,12 @@
 
     uiFrames++;
 
-    // Always import all videos. The video textures are destroyed before the
-    // next frame.
-    // TODO(crbugs.com/1310172): Only import expired video frames.
     for (let i = 0; i < videos.length; ++i) {
-      videoTextures[i] =
-        device.importExternalTexture(externalTextureDescriptor[i]);
-      totalVideoFrames++;
+      if (!videoTextures[i] || videoTextures[i].expired) {
+        videoTextures[i] =
+          device.importExternalTexture(externalTextureDescriptor[i]);
+        totalVideoFrames++;
+      }
     }
 
     const swapChainTexture = context.getCurrentTexture();
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
index c0ba2da..7de3b47 100644
--- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -112,6 +112,9 @@
 crbug.com/1161570 [ mac nvidia debug ] GpuCrash_InfoForHardwareGpu [ Skip ]
 crbug.com/1161570 [ mac nvidia debug ] GpuCrash_InfoForDualHardwareGpus [ Skip ]
 
+# Vulkan enabled on linux, the crash fallback logic is different.
+crbug.com/1334650 [ linux ] GpuCrash_InfoForHardwareGpu [ Skip ]
+
 ###############################
 # Temporary Skip Expectations #
 ###############################
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index 8ba2b982..16cb90d 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -411,6 +411,7 @@
 crbug.com/1307787 [ linux skia-renderer-vulkan ] Pixel_VulkanSwiftShader_WebGPUImportVideoFrameUnacceleratedOffscreenCanvas [ Failure ]
 
 crbug.com/1203317 [ android android-shield-android-tv no-passthrough ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ RetryOnFailure ]
+crbug.com/1203317 [ android android-pixel-2 no-passthrough ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ RetryOnFailure ]
 
 #######################################################################
 # Automated Entries After This Point - Do Not Manually Add Below Here #
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 509e516..f4ab9b92 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -531,6 +531,14 @@
 # Linux AMD RX 5500 XT
 crbug.com/1147232 [ linux amd-0x7340 angle-opengl passthrough ] conformance/textures/misc/texture-size-limit.html [ Failure ]
 
+# Linux NVIDIA / VANGLE - bot NVIDIA driver is too old.
+crbug.com/1271688 [ linux angle-vulkan passthrough nvidia ] conformance/glsl/constructors/glsl-construct-vec-mat-index.html [ Failure ]
+crbug.com/1271688 [ linux angle-vulkan passthrough nvidia ] conformance/glsl/functions/glsl-function-abs.html [ Failure ]
+crbug.com/1271688 [ linux angle-vulkan passthrough nvidia ] conformance/glsl/functions/glsl-function-ceil.html [ Failure ]
+crbug.com/1271688 [ linux angle-vulkan passthrough nvidia ] conformance/glsl/functions/glsl-function-faceforward.html [ Failure ]
+crbug.com/1271688 [ linux angle-vulkan passthrough nvidia ] conformance/ogles/GL/mod/mod_001_to_008.html [ Failure ]
+crbug.com/1271688 [ linux angle-vulkan passthrough nvidia ] conformance/ogles/GL/pow/pow_017_to_024.html [ Failure ]
+
 ####################
 # Android failures #
 ####################
diff --git a/extensions/browser/app_window/app_window_contents.cc b/extensions/browser/app_window/app_window_contents.cc
index 063c6a9..bf230ee 100644
--- a/extensions/browser/app_window/app_window_contents.cc
+++ b/extensions/browser/app_window/app_window_contents.cc
@@ -10,12 +10,14 @@
 
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/app_window/native_app_window.h"
+#include "extensions/browser/bad_message.h"
 #include "extensions/browser/extension_web_contents_observer.h"
 #include "extensions/common/extension_messages.h"
 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
@@ -107,6 +109,9 @@
 
 void AppWindowContentsImpl::DidFinishNavigation(
     content::NavigationHandle* handle) {
+  if (!handle->IsInPrimaryMainFrame())
+    return;
+
   // The callback inside app_window will be moved after the first call.
   host_->OnDidFinishFirstNavigation();
 }
@@ -114,8 +119,15 @@
 void AppWindowContentsImpl::UpdateDraggableRegions(
     content::RenderFrameHost* sender,
     const std::vector<DraggableRegion>& regions) {
-  if (!sender->GetParent())  // Only process events from the main frame.
-    host_->UpdateDraggableRegions(regions);
+  // This message should come from a primary main frame.
+  if (!sender->IsInPrimaryMainFrame()) {
+    bad_message::ReceivedBadMessage(
+        web_contents_->GetMainFrame()->GetProcess(),
+        bad_message::AWCI_INVALID_CALL_FROM_NOT_PRIMARY_MAIN_FRAME);
+    return;
+  }
+
+  host_->UpdateDraggableRegions(regions);
 }
 
 }  // namespace extensions
diff --git a/extensions/browser/bad_message.h b/extensions/browser/bad_message.h
index e56bf2c..93ffd3e 100644
--- a/extensions/browser/bad_message.h
+++ b/extensions/browser/bad_message.h
@@ -42,6 +42,7 @@
   EMF_INVALID_EXTENSION_ID_FOR_CONTENT_SCRIPT = 16,
   EMF_INVALID_EXTENSION_ID_FOR_WORKER_CONTEXT = 17,
   EMF_INVALID_PORT_CONTEXT = 18,
+  AWCI_INVALID_CALL_FROM_NOT_PRIMARY_MAIN_FRAME = 19,
   // Please add new elements here. The naming convention is abbreviated class
   // name (e.g. ExtensionHost becomes EH) plus a unique description of the
   // reason. After making changes, you MUST update histograms.xml by running:
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json
index 1c418af..31b9567 100644
--- a/extensions/common/api/_api_features.json
+++ b/extensions/common/api/_api_features.json
@@ -376,8 +376,6 @@
       "896B85CC7E913E11C34892C1425A093C0701D386",  // http://crbug.com/456214
       "11A01C82EF355E674E4F9728A801F5C3CB40D83F",  // http://crbug.com/456214
       "F410C88469990EE7947450311D24B8AF2ADB2595",  // http://crbug.com/456214
-      "63ED55E43214C211F82122ED56407FF1A807F2A3",  // Media Router Dev
-      "226CF815E39A363090A1E547D53063472B8279FA",  // Media Router Stable
       // TODO (ntang) Remove the following 2 hashes by 12/31/2017.
       "B620CF4203315F9F2E046EDED22C7571A935958D",  // http://crbug.com/510270
       "B206D8716769728278D2D300349C6CB7D7DE2EF9",  // http://crbug.com/510270
@@ -404,8 +402,6 @@
     "channel": "stable",
     "extension_types": ["platform_app", "extension"],
     "allowlist": [
-      "63ED55E43214C211F82122ED56407FF1A807F2A3",   // Media Router Dev
-      "226CF815E39A363090A1E547D53063472B8279FA",   // Media Router Stable
       "B41E7F08E1179CC03CBD1F49E57CF353A40ADE07",   // Chrome Camera App Dev
       "A3E3DE9E9F16B41D4A2FAD106BD6CA76B94A0C94"    // Chrome Camera App Stable
     ]
diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json
index 388a0fa..83acfdf54 100644
--- a/extensions/common/api/_permission_features.json
+++ b/extensions/common/api/_permission_features.json
@@ -416,8 +416,6 @@
       "C449A798C495E6CF7D6AF10162113D564E67AD12",  // CRD Dogfood
       "01E9FFA9A8F3C18271FE91BEE46207F3B81755CC",  // Pre-release CRD
       "97B23E01B2AA064E8332EE43A7A85C628AADC3F2",  // Sample app_remoting app.
-      "63ED55E43214C211F82122ED56407FF1A807F2A3",  // Media Router Dev
-      "226CF815E39A363090A1E547D53063472B8279FA",  // Media Router Stable
       "0EA6B717932AD64C469C1CCB6911457733295907",  // Secure Shell App (stable)
       "58B0C2968C335964D5433E89CA4D86628A0E3D4B",  // Secure Shell App (dev)
       "3BC1ED0B3E6EFDC7BD4D3D1D75D44B52DEE0A226",  // Secure Shell Ext (stable)
@@ -461,8 +459,6 @@
       "8C3741E3AF0B93B6E8E0DDD499BB0B74839EA578",  // http://crbug.com/234235
       "E703483CEF33DEC18B4B6DD84B5C776FB9182BDB",  // http://crbug.com/234235
       "307E96539209F95A1A8740C713E6998A73657D96",  // http://crbug.com/329690
-      "63ED55E43214C211F82122ED56407FF1A807F2A3",  // Media Router Dev
-      "226CF815E39A363090A1E547D53063472B8279FA",  // Media Router Stable
       "7AE714FFD394E073F0294CFA134C9F91DB5FBAA4",  // CCD Development
       "C7DA3A55C2355F994D3FDDAD120B426A0DF63843",  // CCD Testing
       "75E3CFFFC530582C583E4690EF97C70B9C8423B7",  // CCD Release
@@ -508,12 +504,6 @@
       "8C3741E3AF0B93B6E8E0DDD499BB0B74839EA578",  // http://crbug.com/234235
       "E703483CEF33DEC18B4B6DD84B5C776FB9182BDB",  // http://crbug.com/234235
       "307E96539209F95A1A8740C713E6998A73657D96",  // http://crbug.com/329690
-      "63ED55E43214C211F82122ED56407FF1A807F2A3",  // Dev
-      "FA01E0B81978950F2BC5A50512FD769725F57510",  // Beta
-      "B11A93E7E5B541F8010245EBDE2C74647D6C14B9",  // Canary
-      "F155646B5D1CA545F7E1E4E20D573DFDD44C2540",  // Google Cast Beta
-      "16CA7A47AAE4BE49B1E75A6B960C3875E945B264",  // Google Cast Stable
-      "226CF815E39A363090A1E547D53063472B8279FA",  // http://crbug.com/588179
       "7AE714FFD394E073F0294CFA134C9F91DB5FBAA4",  // CCD Development
       "C7DA3A55C2355F994D3FDDAD120B426A0DF63843",  // CCD Testing
       "75E3CFFFC530582C583E4690EF97C70B9C8423B7",  // CCD Release
diff --git a/extensions/renderer/native_extension_bindings_system_unittest.cc b/extensions/renderer/native_extension_bindings_system_unittest.cc
index 887cd27..5ad9674 100644
--- a/extensions/renderer/native_extension_bindings_system_unittest.cc
+++ b/extensions/renderer/native_extension_bindings_system_unittest.cc
@@ -469,9 +469,8 @@
 
   // The 'chrome.app' object should have 'runtime' and 'window' entries, but
   // not the internal 'currentWindowInternal' object.
-  v8::Local<v8::Value> app_binding_keys =
-      V8ValueFromScriptSource(context,
-                              "JSON.stringify(Object.keys(chrome.app));");
+  v8::Local<v8::Value> app_binding_keys = V8ValueFromScriptSource(
+      context, "JSON.stringify(Object.keys(chrome.app));");
   ASSERT_FALSE(app_binding_keys.IsEmpty());
   ASSERT_TRUE(app_binding_keys->IsString());
   EXPECT_EQ("[\"runtime\",\"window\"]",
@@ -923,7 +922,7 @@
 // does not allow for accessing the source API (networkingPrivate) directly.
 TEST_F(NativeExtensionBindingsSystemUnittest,
        AccessToAliasSourceDoesntGiveAliasAccess) {
-  const char kAllowlistedId[] = "pkedcjkdefgpdelpbcmbmeomcjbeemfm";
+  const char kAllowlistedId[] = "jlgegmdnodfhciolbdjciihnlaljdbjo";
   scoped_refptr<const Extension> extension =
       ExtensionBuilder("extension")
           .SetID(kAllowlistedId)
@@ -955,7 +954,7 @@
 // allow for accessing the alias.
 TEST_F(NativeExtensionBindingsSystemUnittest,
        AccessToAliasDoesntGiveAliasSourceAccess) {
-  const char kAllowlistedId[] = "pkedcjkdefgpdelpbcmbmeomcjbeemfm";
+  const char kAllowlistedId[] = "jlgegmdnodfhciolbdjciihnlaljdbjo";
   scoped_refptr<const Extension> extension =
       ExtensionBuilder("extension")
           .SetID(kAllowlistedId)
@@ -985,7 +984,7 @@
 // Test that if an extension has access to both an alias and an alias source,
 // the objects on the API are different.
 TEST_F(NativeExtensionBindingsSystemUnittest, AliasedAPIsAreDifferentObjects) {
-  const char kAllowlistedId[] = "pkedcjkdefgpdelpbcmbmeomcjbeemfm";
+  const char kAllowlistedId[] = "jlgegmdnodfhciolbdjciihnlaljdbjo";
   scoped_refptr<const Extension> extension =
       ExtensionBuilder("extension")
           .SetID(kAllowlistedId)
diff --git a/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc b/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc
index caa2916..e055614 100644
--- a/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc
+++ b/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc
@@ -84,27 +84,6 @@
       ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
 }
 
-static constexpr char const* kRendererSwitchesToCopy[] = {
-    blink::switches::kSharedArrayBufferAllowedOrigins,
-    switches::kCorsExemptHeaders,
-    switches::kEnableCastStreamingReceiver,
-    switches::kEnableContentDirectories,
-    switches::kEnableProtectedVideoBuffers,
-    switches::kUseOverlaysForVideo,
-
-    // TODO(crbug/1013412): Delete these two switches when fixed.
-    switches::kEnableWidevine,
-    switches::kPlayreadyKeySystem,
-
-    // Pass to the renderer process for consistency with Chrome.
-    network::switches::kUnsafelyTreatInsecureOriginAsSecure,
-};
-
-static constexpr char const*
-    kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy[] = {
-        network::switches::kUnsafelyTreatInsecureOriginAsSecure,
-};
-
 }  // namespace
 
 WebEngineContentBrowserClient::WebEngineContentBrowserClient()
@@ -208,24 +187,22 @@
 void WebEngineContentBrowserClient::AppendExtraCommandLineSwitches(
     base::CommandLine* command_line,
     int child_process_id) {
-  std::string process_type =
-      command_line->GetSwitchValueASCII(switches::kProcessType);
+  // TODO(https://crbug.com/1083520): Pass based on process type.
+  constexpr char const* kSwitchesToCopy[] = {
+      blink::switches::kSharedArrayBufferAllowedOrigins,
+      switches::kCorsExemptHeaders,
+      switches::kEnableCastStreamingReceiver,
+      switches::kEnableContentDirectories,
+      switches::kEnableProtectedVideoBuffers,
+      switches::kEnableWidevine,
+      switches::kMaxDecodedImageSizeMb,
+      switches::kPlayreadyKeySystem,
+      network::switches::kUnsafelyTreatInsecureOriginAsSecure,
+      switches::kUseOverlaysForVideo,
+  };
 
-  if (process_type == switches::kRendererProcess) {
-    command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
-                                   kRendererSwitchesToCopy,
-                                   std::size(kRendererSwitchesToCopy));
-  } else if (process_type == switches::kUtilityProcess) {
-    // Although only the Network process needs
-    // kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy, differentiating utility
-    // process sub-types is non-trivial. ChromeContentBrowserClient appends this
-    // switch to all Utility processes so do the same here.
-    // Do not add other switches here.
-    command_line->CopySwitchesFrom(
-        *base::CommandLine::ForCurrentProcess(),
-        kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy,
-        std::size(kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy));
-  }
+  command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
+                                 kSwitchesToCopy, std::size(kSwitchesToCopy));
 }
 
 std::string WebEngineContentBrowserClient::GetApplicationLocale() {
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc
index a647664b..b18dd1f 100644
--- a/gpu/command_buffer/service/webgpu_decoder_impl.cc
+++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -1034,7 +1034,6 @@
     case WGPUFeatureName_ChromiumExperimentalDp4a:
     case WGPUFeatureName_DawnMultiPlanarFormats:
       return allow_unsafe_apis_;
-    case WGPUFeatureName_Depth24UnormStencil8:
     case WGPUFeatureName_Depth32FloatStencil8:
     case WGPUFeatureName_TextureCompressionBC:
     case WGPUFeatureName_TextureCompressionETC2:
diff --git a/ios/chrome/browser/ui/settings/privacy/BUILD.gn b/ios/chrome/browser/ui/settings/privacy/BUILD.gn
index 24b4b9e..771c821 100644
--- a/ios/chrome/browser/ui/settings/privacy/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/privacy/BUILD.gn
@@ -152,24 +152,3 @@
     "//ui/base",
   ]
 }
-
-source_set("eg2_tests") {
-  configs += [
-    "//build/config/compiler:enable_arc",
-    "//build/config/ios:xctest_config",
-  ]
-  testonly = true
-  sources = [ "privacy_safe_browsing_egtest.mm" ]
-  deps = [
-    "//base",
-    "//components/safe_browsing/core/common:safe_browsing_prefs",
-    "//components/strings:components_strings_grit",
-    "//ios/chrome/app/strings:ios_strings_grit",
-    "//ios/chrome/browser/ui/settings/privacy:privacy_constants",
-    "//ios/chrome/test/earl_grey:eg_test_support+eg2",
-    "//ios/testing/earl_grey:eg_test_support+eg2",
-    "//ios/third_party/earl_grey2:test_lib",
-    "//ui/base",
-  ]
-  frameworks = [ "UIKit.framework" ]
-}
diff --git a/ios/chrome/browser/ui/settings/privacy/privacy_safe_browsing_egtest.mm b/ios/chrome/browser/ui/settings/privacy/privacy_safe_browsing_egtest.mm
deleted file mode 100644
index ef9fcfa..0000000
--- a/ios/chrome/browser/ui/settings/privacy/privacy_safe_browsing_egtest.mm
+++ /dev/null
@@ -1,115 +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.
-
-#import "components/safe_browsing/core/common/safe_browsing_prefs.h"
-#import "components/strings/grit/components_strings.h"
-#import "ios/chrome/browser/ui/settings/privacy/privacy_constants.h"
-#import "ios/chrome/grit/ios_strings.h"
-#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
-#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
-#import "ios/chrome/test/earl_grey/chrome_matchers.h"
-#import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/testing/earl_grey/earl_grey_test.h"
-#import "ui/base/l10n/l10n_util.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-using chrome_test_util::ButtonWithAccessibilityLabelId;
-using chrome_test_util::SettingsDoneButton;
-using chrome_test_util::SettingsMenuPrivacyButton;
-using l10n_util::GetNSString;
-
-// Integration tests using the Privacy Safe Browsing settings screen.
-@interface PrivacySafeBrowsingTestCase : ChromeTestCase
-@end
-
-@implementation PrivacySafeBrowsingTestCase
-
-- (void)testOpenPrivacySafeBrowsingSettings {
-  [self openPrivacySafeBrowsingSettings];
-}
-
-// TODO(crbug.com/1333625): Enable once activation point is fixed.
-- (void)DISABLED_testEachSafeBrowsingOption {
-  [self openPrivacySafeBrowsingSettings];
-
-  // Presses each of the Safe Browsing options.
-  [[EarlGrey
-      selectElementWithMatcher:
-          grey_accessibilityID(kSettingsSafeBrowsingEnhancedProtectionCellId)]
-      performAction:grey_tap()];
-  GREYAssertTrue([ChromeEarlGrey userBooleanPref:prefs::kSafeBrowsingEnhanced],
-                 @"Failed to toggle-on Enhanced Safe Browsing");
-
-  [[EarlGrey
-      selectElementWithMatcher:
-          grey_accessibilityID(kSettingsSafeBrowsingStandardProtectionCellId)]
-      performAction:grey_tap()];
-  GREYAssertFalse([ChromeEarlGrey userBooleanPref:prefs::kSafeBrowsingEnhanced],
-                  @"Failed to toggle-off Enhanced Safe Browsing");
-  GREYAssertTrue([ChromeEarlGrey userBooleanPref:prefs::kSafeBrowsingEnabled],
-                 @"Failed to toggle-on Standard Safe Browsing");
-
-  [[EarlGrey
-      selectElementWithMatcher:grey_accessibilityID(
-                                   kSettingsSafeBrowsingNoProtectionCellId)]
-      performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:grey_buttonTitle(GetNSString(IDS_CANCEL))]
-      performAction:grey_tap()];
-  GREYAssertFalse([ChromeEarlGrey userBooleanPref:prefs::kSafeBrowsingEnhanced],
-                  @"Failed to keep Enhanced Safe Browsing off");
-  GREYAssertTrue([ChromeEarlGrey userBooleanPref:prefs::kSafeBrowsingEnabled],
-                 @"Failed to keep Standard Safe Browsing on");
-
-  [[EarlGrey
-      selectElementWithMatcher:grey_accessibilityID(
-                                   kSettingsSafeBrowsingNoProtectionCellId)]
-      performAction:grey_tap()];
-  [[EarlGrey
-      selectElementWithMatcher:
-          grey_buttonTitle(GetNSString(
-              IDS_IOS_SAFE_BROWSING_NO_PROTECTION_CONFIRMATION_DIALOG_CONFIRM))]
-      performAction:grey_tap()];
-  GREYAssertFalse([ChromeEarlGrey userBooleanPref:prefs::kSafeBrowsingEnabled],
-                  @"Failed to toggle-off Standard Safe Browsing");
-}
-
-- (void)testPrivacySafeBrowsingDoneButton {
-  [self openPrivacySafeBrowsingSettings];
-  [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
-      performAction:grey_tap()];
-}
-
-- (void)testPrivacySafeBrowsingSwipeDown {
-  [self openPrivacySafeBrowsingSettings];
-
-  // Check that ESB is presented.
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
-                                          kPrivacySafeBrowsingTableViewId)]
-      assertWithMatcher:grey_notNil()];
-
-  // Swipe TableView down.
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
-                                          kPrivacySafeBrowsingTableViewId)]
-      performAction:grey_swipeFastInDirection(kGREYDirectionDown)];
-
-  // Check that Settings has been dismissed.
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
-                                          kPrivacySafeBrowsingTableViewId)]
-      assertWithMatcher:grey_nil()];
-}
-
-#pragma mark - Helpers
-
-- (void)openPrivacySafeBrowsingSettings {
-  [ChromeEarlGreyUI openSettingsMenu];
-  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsMenuPrivacyButton()];
-  [ChromeEarlGreyUI
-      tapPrivacyMenuButton:ButtonWithAccessibilityLabelId(
-                               IDS_IOS_PRIVACY_SAFE_BROWSING_TITLE)];
-}
-
-@end
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
index ee7f440f..7202c60 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
+++ b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
@@ -806,7 +806,11 @@
 }
 
 + (id<GREYMatcher>)systemSelectionCallout {
-  return grey_kindOfClass(NSClassFromString(@"UICalloutBarButton"));
+  if (@available(iOS 16.0, *)) {
+    return grey_kindOfClass(NSClassFromString(@"_UIEditMenuListViewCell"));
+  } else {
+    return grey_kindOfClass(NSClassFromString(@"UICalloutBarButton"));
+  }
 }
 
 + (id<GREYMatcher>)systemSelectionCalloutLinkToTextButton {
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn
index 707e2b2e..0a26efd 100644
--- a/ios/chrome/test/earl_grey2/BUILD.gn
+++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -131,7 +131,6 @@
     "//ios/chrome/browser/ui/settings/language:eg2_tests",
     "//ios/chrome/browser/ui/settings/password:eg2_tests",
     "//ios/chrome/browser/ui/settings/password/passwords_in_other_apps:eg2_tests",
-    "//ios/chrome/browser/ui/settings/privacy:eg2_tests",
     "//ios/chrome/browser/ui/settings/sync:eg2_tests",
   ]
   data_deps = [ ":ios_chrome_eg2tests" ]
diff --git a/net/cert/internal/parse_certificate.cc b/net/cert/internal/parse_certificate.cc
index 2dddf9d..79cc951 100644
--- a/net/cert/internal/parse_certificate.cc
+++ b/net/cert/internal/parse_certificate.cc
@@ -236,6 +236,9 @@
 
 ParsedTbsCertificate::ParsedTbsCertificate() = default;
 
+ParsedTbsCertificate::ParsedTbsCertificate(ParsedTbsCertificate&& other) =
+    default;
+
 ParsedTbsCertificate::~ParsedTbsCertificate() = default;
 
 bool VerifySerialNumber(const der::Input& value,
diff --git a/net/cert/internal/parse_certificate.h b/net/cert/internal/parse_certificate.h
index ea03bf8..9e5e9fd1 100644
--- a/net/cert/internal/parse_certificate.h
+++ b/net/cert/internal/parse_certificate.h
@@ -190,6 +190,8 @@
 // sets.
 struct NET_EXPORT ParsedTbsCertificate {
   ParsedTbsCertificate();
+  ParsedTbsCertificate(ParsedTbsCertificate&& other);
+  ParsedTbsCertificate& operator=(ParsedTbsCertificate&& other) = default;
   ~ParsedTbsCertificate();
 
   // Corresponds with "version" from RFC 5280:
diff --git a/pdf/pdf_view_plugin_base.h b/pdf/pdf_view_plugin_base.h
index 701483b2..2bc59f1 100644
--- a/pdf/pdf_view_plugin_base.h
+++ b/pdf/pdf_view_plugin_base.h
@@ -26,7 +26,6 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/web/web_print_params.h"
 #include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 
@@ -298,11 +297,6 @@
 
   void set_url(std::string url) { url_ = std::move(url); }
 
-  ui::mojom::CursorType cursor_type() const { return cursor_type_; }
-  void set_cursor_type(ui::mojom::CursorType cursor_type) {
-    cursor_type_ = cursor_type;
-  }
-
   const std::string& link_under_cursor() const { return link_under_cursor_; }
 
   virtual bool full_frame() const = 0;
@@ -413,9 +407,6 @@
   // The URL of the PDF document.
   std::string url_;
 
-  // The current cursor type.
-  ui::mojom::CursorType cursor_type_ = ui::mojom::CursorType::kPointer;
-
   // The URL currently under the cursor.
   std::string link_under_cursor_;
 
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc
index 4669a29..f2b87262 100644
--- a/pdf/pdf_view_web_plugin.cc
+++ b/pdf/pdf_view_web_plugin.cc
@@ -445,7 +445,7 @@
           ? blink::WebInputEventResult::kHandledApplication
           : blink::WebInputEventResult::kNotHandled;
 
-  *cursor = cursor_type();
+  *cursor = cursor_type_;
 
   return result;
 }
@@ -649,7 +649,7 @@
 }
 
 void PdfViewWebPlugin::UpdateCursor(ui::mojom::CursorType new_cursor_type) {
-  set_cursor_type(new_cursor_type);
+  cursor_type_ = new_cursor_type;
 }
 
 void PdfViewWebPlugin::UpdateTickMarks(
diff --git a/pdf/pdf_view_web_plugin.h b/pdf/pdf_view_web_plugin.h
index ca988a0d..62aeb3c 100644
--- a/pdf/pdf_view_web_plugin.h
+++ b/pdf/pdf_view_web_plugin.h
@@ -32,6 +32,7 @@
 #include "third_party/blink/public/web/web_plugin_container.h"
 #include "third_party/blink/public/web/web_plugin_params.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 #include "v8/include/v8.h"
 
@@ -425,6 +426,9 @@
 
   std::unique_ptr<PDFiumEngine> engine_;
 
+  // The current cursor type.
+  ui::mojom::CursorType cursor_type_ = ui::mojom::CursorType::kPointer;
+
   // The id of the current find operation, or -1 if no current operation is
   // present.
   int find_identifier_ = -1;
diff --git a/remoting/codec/webrtc_video_encoder_gpu.cc b/remoting/codec/webrtc_video_encoder_gpu.cc
index f851b11..eeaee9e 100644
--- a/remoting/codec/webrtc_video_encoder_gpu.cc
+++ b/remoting/codec/webrtc_video_encoder_gpu.cc
@@ -356,9 +356,11 @@
 #endif
 
   VideoPixelFormat input_format = VideoPixelFormat::PIXEL_FORMAT_NV12;
-  // TODO(zijiehe): implement some logical way to set an initial bitrate.
+  // TODO(zijiehe): Implement some logical way to set an initial bitrate.
   // Currently we set the bitrate to 8M bits / 1M bytes per frame, and 30 frames
   // per second.
+  // TODO(joedow): Use the framerate from SessionOptions instead of the constant
+  // framerate value if we decide to make H.264 generally available.
   media::Bitrate initial_bitrate = media::Bitrate::ConstantBitrate(
       static_cast<uint32_t>(kTargetFrameRate * 1024 * 1024 * 8));
 
diff --git a/remoting/protocol/webrtc_frame_scheduler_constant_rate.cc b/remoting/protocol/webrtc_frame_scheduler_constant_rate.cc
index 0f379a1..4011598 100644
--- a/remoting/protocol/webrtc_frame_scheduler_constant_rate.cc
+++ b/remoting/protocol/webrtc_frame_scheduler_constant_rate.cc
@@ -118,7 +118,7 @@
   if (!last_capture_started_time_.is_null()) {
     base::TimeTicks target_capture_time =
         std::max(last_capture_started_time_ + capture_interval, now);
-    delay = target_capture_time - now;
+    delay = std::max(target_capture_time - now, base::Milliseconds(1));
   }
 
   capture_timer_.Start(FROM_HERE, delay, this,
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc
index 48a3850..2760bc0c 100644
--- a/remoting/protocol/webrtc_transport.cc
+++ b/remoting/protocol/webrtc_transport.cc
@@ -13,6 +13,7 @@
 #include "base/base64.h"
 #include "base/bind.h"
 #include "base/command_line.h"
+#include "base/cxx17_backports.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -144,7 +145,8 @@
 // Initializes default parameters for a sender that may be different from
 // WebRTC's defaults.
 void SetDefaultSenderParameters(
-    rtc::scoped_refptr<webrtc::RtpSenderInterface> sender) {
+    rtc::scoped_refptr<webrtc::RtpSenderInterface> sender,
+    int video_frame_rate) {
   if (sender->media_type() == cricket::MEDIA_TYPE_VIDEO) {
     webrtc::RtpParameters parameters = sender->GetParameters();
     if (parameters.encodings.empty()) {
@@ -153,7 +155,7 @@
     }
 
     for (auto& encoding : parameters.encodings) {
-      encoding.max_framerate = kTargetFrameRate;
+      encoding.max_framerate = video_frame_rate;
     }
 
     webrtc::RTCError result = sender->SetParameters(parameters);
@@ -745,6 +747,16 @@
   if (video_codec) {
     preferred_video_codec_ = *video_codec;
   }
+  absl::optional<std::string> video_frame_rate =
+      session_options().Get("Video-Frame-Rate");
+  if (video_frame_rate) {
+    int frame_rate;
+    if (base::StringToInt(*video_frame_rate, &frame_rate)) {
+      // Clamp the range to prevent a bad experience in case of a client bug.
+      frame_rate = base::clamp<int>(frame_rate, kTargetFrameRate, 1000);
+      desired_video_frame_rate_ = frame_rate;
+    }
+  }
 }
 
 void WebrtcTransport::OnAudioTransceiverCreated(
@@ -757,7 +769,7 @@
   auto sender = transceiver->sender();
   auto [min_bitrate_bps, max_bitrate_bps] = BitratesForConnection();
   SetSenderBitrates(sender, min_bitrate_bps, max_bitrate_bps);
-  SetDefaultSenderParameters(sender);
+  SetDefaultSenderParameters(sender, desired_video_frame_rate_);
 }
 
 void WebrtcTransport::OnLocalSessionDescriptionCreated(
@@ -845,7 +857,7 @@
   // maximum framerate.
   auto senders = peer_connection()->GetSenders();
   for (const auto& sender : senders) {
-    SetDefaultSenderParameters(sender);
+    SetDefaultSenderParameters(sender, desired_video_frame_rate_);
   }
 }
 
diff --git a/remoting/protocol/webrtc_transport.h b/remoting/protocol/webrtc_transport.h
index a347a4d7..5468dcc 100644
--- a/remoting/protocol/webrtc_transport.h
+++ b/remoting/protocol/webrtc_transport.h
@@ -17,6 +17,7 @@
 #include "base/threading/thread_checker.h"
 #include "base/timer/timer.h"
 #include "crypto/hmac.h"
+#include "remoting/base/constants.h"
 #include "remoting/base/session_options.h"
 #include "remoting/protocol/peer_connection_controls.h"
 #include "remoting/protocol/session_options_provider.h"
@@ -253,6 +254,7 @@
       pending_incoming_candidates_;
 
   std::string preferred_video_codec_;
+  int desired_video_frame_rate_ = kTargetFrameRate;
 
   SessionOptions session_options_;
 
diff --git a/services/network/cookie_settings.cc b/services/network/cookie_settings.cc
index 3a91f40a..256c614 100644
--- a/services/network/cookie_settings.cc
+++ b/services/network/cookie_settings.cc
@@ -176,14 +176,13 @@
   // No unpartitioned cookie should be sent on this request. The only other
   // options are to block all cookies, or allow just partitioned cookies.
 
-  switch (metadata.blocked_by_third_party_setting) {
-    case ThirdPartyCookieBlockingSetting::kThirdPartyStateAllowed:
+  switch (metadata.third_party_blocking_outcome) {
+    case ThirdPartyBlockingOutcome::kIrrelevant:
       [[fallthrough]];
-    case ThirdPartyCookieBlockingSetting::kThirdPartyStateDisallowed:
+    case ThirdPartyBlockingOutcome::kAllStateDisallowed:
       return net::NetworkDelegate::PrivacySetting::kStateDisallowed;
 
-    case ThirdPartyCookieBlockingSetting::
-        kPartitionedThirdPartyStateAllowedOnly:
+    case ThirdPartyBlockingOutcome::kPartitionedStateAllowed:
       return net::NetworkDelegate::PrivacySetting::kPartitionedStateAllowedOnly;
   }
 }
@@ -196,20 +195,20 @@
   if (ShouldAlwaysAllowCookies(url, first_party_url)) {
     return {
         /*cookie_setting=*/CONTENT_SETTING_ALLOW,
-        /*blocked_by_third_party_setting=*/
-        ThirdPartyCookieBlockingSetting::kThirdPartyStateAllowed,
+        /*third_party_blocking_outcome=*/
+        ThirdPartyBlockingOutcome::kIrrelevant,
     };
   }
 
   // Default to allowing cookies.
   ContentSetting cookie_setting = CONTENT_SETTING_ALLOW;
-  ThirdPartyCookieBlockingSetting blocked_by_third_party_setting =
-      ThirdPartyCookieBlockingSetting::kThirdPartyStateAllowed;
+  ThirdPartyBlockingOutcome third_party_blocking_outcome =
+      ThirdPartyBlockingOutcome::kIrrelevant;
   if (block_third_party_cookies_ && is_third_party_request &&
       !base::Contains(third_party_cookies_allowed_schemes_,
                       first_party_url.scheme())) {
-    blocked_by_third_party_setting =
-        ThirdPartyCookieBlockingSetting::kThirdPartyStateDisallowed;
+    third_party_blocking_outcome =
+        ThirdPartyBlockingOutcome::kAllStateDisallowed;
   }
 
   if (const ContentSettingPatternSource* match =
@@ -217,27 +216,24 @@
       match) {
     cookie_setting = match->GetContentSetting();
     if (cookie_setting == CONTENT_SETTING_BLOCK || IsExplicitSetting(*match)) {
-      blocked_by_third_party_setting =
-          ThirdPartyCookieBlockingSetting::kThirdPartyStateAllowed;
+      third_party_blocking_outcome = ThirdPartyBlockingOutcome::kIrrelevant;
     }
   }
 
-  if (blocked_by_third_party_setting ==
-      ThirdPartyCookieBlockingSetting::kThirdPartyStateDisallowed) {
+  if (third_party_blocking_outcome ==
+      ThirdPartyBlockingOutcome::kAllStateDisallowed) {
     if (const ContentSettingPatternSource* match =
             FindMatchingSetting(url, first_party_url, storage_access_grants_);
         match) {
       if (match->GetContentSetting() == CONTENT_SETTING_ALLOW) {
-        blocked_by_third_party_setting =
-            ThirdPartyCookieBlockingSetting::kThirdPartyStateAllowed;
+        third_party_blocking_outcome = ThirdPartyBlockingOutcome::kIrrelevant;
         FireStorageAccessHistogram(net::cookie_util::StorageAccessResult::
                                        ACCESS_ALLOWED_STORAGE_ACCESS_GRANT);
       }
     }
 
-    if (blocked_by_third_party_setting ==
-        CookieSettings::ThirdPartyCookieBlockingSetting::
-            kThirdPartyStateDisallowed) {
+    if (third_party_blocking_outcome ==
+        ThirdPartyBlockingOutcome::kAllStateDisallowed) {
       // If the third-party cookie blocking setting is enabled, we check if the
       // user has any content settings for the first-party URL as the primary
       // pattern. If cookies are allowed for the first-party URL then we allow
@@ -245,8 +241,8 @@
       if (const ContentSettingPatternSource* match = FindMatchingSetting(
               first_party_url, first_party_url, content_settings_);
           !match || match->GetContentSetting() == CONTENT_SETTING_ALLOW) {
-        blocked_by_third_party_setting = ThirdPartyCookieBlockingSetting::
-            kPartitionedThirdPartyStateAllowedOnly;
+        third_party_blocking_outcome =
+            ThirdPartyBlockingOutcome::kPartitionedStateAllowed;
       }
     }
   } else {
@@ -259,14 +255,13 @@
             : net::cookie_util::StorageAccessResult::ACCESS_ALLOWED);
   }
 
-  if (blocked_by_third_party_setting !=
-      ThirdPartyCookieBlockingSetting::kThirdPartyStateAllowed) {
+  if (third_party_blocking_outcome != ThirdPartyBlockingOutcome::kIrrelevant) {
     cookie_setting = CONTENT_SETTING_BLOCK;
     FireStorageAccessHistogram(
         net::cookie_util::StorageAccessResult::ACCESS_BLOCKED);
   }
 
-  return {cookie_setting, blocked_by_third_party_setting};
+  return {cookie_setting, third_party_blocking_outcome};
 }
 
 CookieSettings::CookieSettingWithMetadata
@@ -348,12 +343,11 @@
 
 bool CookieSettings::IsAllowedSamePartyCookie(
     bool is_same_party,
-    ThirdPartyCookieBlockingSetting third_party_cookie_blocking_setting,
+    ThirdPartyBlockingOutcome third_party_blocking_outcome,
     bool record_metrics) const {
   bool blocked_by_3p_but_same_party =
       is_same_party &&
-      third_party_cookie_blocking_setting !=
-          ThirdPartyCookieBlockingSetting::kThirdPartyStateAllowed;
+      third_party_blocking_outcome != ThirdPartyBlockingOutcome::kIrrelevant;
   if (record_metrics && blocked_by_3p_but_same_party) {
     UMA_HISTOGRAM_BOOLEAN(
         "Cookie.SameParty.BlockedByThirdPartyCookieBlockingSetting",
@@ -367,10 +361,10 @@
 // static
 bool CookieSettings::IsAllowedPartitionedCookie(
     bool is_partitioned,
-    ThirdPartyCookieBlockingSetting third_party_cookie_blocking_setting) {
-  return is_partitioned && third_party_cookie_blocking_setting ==
-                               ThirdPartyCookieBlockingSetting::
-                                   kPartitionedThirdPartyStateAllowedOnly;
+    ThirdPartyBlockingOutcome third_party_blocking_outcome) {
+  return is_partitioned &&
+         third_party_blocking_outcome ==
+             ThirdPartyBlockingOutcome::kPartitionedStateAllowed;
 }
 
 bool CookieSettings::IsHypotheticalCookieAllowed(
@@ -381,12 +375,11 @@
   DCHECK(!is_partitioned || !is_same_party);
   return IsAllowed(setting_with_metadata.cookie_setting) ||
          IsAllowedSamePartyCookie(
-             is_same_party,
-             setting_with_metadata.blocked_by_third_party_setting,
+             is_same_party, setting_with_metadata.third_party_blocking_outcome,
              record_metrics) ||
          IsAllowedPartitionedCookie(
              is_partitioned,
-             setting_with_metadata.blocked_by_third_party_setting);
+             setting_with_metadata.third_party_blocking_outcome);
 }
 
 bool CookieSettings::HasSessionOnlyOrigins() const {
diff --git a/services/network/cookie_settings.h b/services/network/cookie_settings.h
index 7ef42bf..d23edcf 100644
--- a/services/network/cookie_settings.h
+++ b/services/network/cookie_settings.h
@@ -154,17 +154,27 @@
       bool is_third_party_request,
       content_settings::SettingSource* source) const override;
 
-  enum class ThirdPartyCookieBlockingSetting {
-    kThirdPartyStateAllowed = 1,
-    kThirdPartyStateDisallowed,
-    kPartitionedThirdPartyStateAllowedOnly,
+  // An enum that represents the result of applying the user's
+  // third-party-cookie-blocking setting in a given context.
+  enum class ThirdPartyBlockingOutcome {
+    // Access is not blocked due to the third-party-cookie-blocking setting,
+    // either because there's a more specific reason to block access, or because
+    // the context isn't "third-party", or because the access isn't blocked at
+    // all.
+    kIrrelevant = 1,
+    // Access to all cookies (partitioned or unpartitioned) is blocked in this
+    // context.
+    kAllStateDisallowed,
+    // Access to unpartitioned cookies is blocked in this context, but access to
+    // partitioned cookies is allowed.
+    kPartitionedStateAllowed,
   };
 
   struct CookieSettingWithMetadata {
     ContentSetting cookie_setting;
     // Only relevant if access to the cookie is blocked for some reason (i.e. if
     // `IsAllow(cookie_setting)` is false).
-    ThirdPartyCookieBlockingSetting blocked_by_third_party_setting;
+    ThirdPartyBlockingOutcome third_party_blocking_outcome;
   };
 
   // Returns the cookie setting for the given request, along with metadata
@@ -192,19 +202,19 @@
 
   // Returns true iff a cookie with the given `is_same_party` property should be
   // accessible in a context with the given
-  // `third_party_cookie_blocking_setting`. Records metrics iff `record_metrics`
+  // `third_party_blocking_outcome`. Records metrics iff `record_metrics`
   // is true.
   bool IsAllowedSamePartyCookie(
       bool is_same_party,
-      ThirdPartyCookieBlockingSetting third_party_cookie_blocking_setting,
+      ThirdPartyBlockingOutcome third_party_blocking_outcome,
       bool record_metrics) const;
 
   // Returns true iff a cookie with the given `is_partitioned` property should
   // be accessible in a context with the given
-  // `third_party_cookie_blocking_setting`.
+  // `third_party_blocking_outcome`.
   static bool IsAllowedPartitionedCookie(
       bool is_partitioned,
-      ThirdPartyCookieBlockingSetting third_party_cookie_blocking_setting);
+      ThirdPartyBlockingOutcome third_party_blocking_outcome);
 
   // Returns whether *some* cookie would be allowed to be sent in this context,
   // according to the user's settings. Note that cookies may still be "excluded"
diff --git a/services/network/public/mojom/fetch_api.mojom b/services/network/public/mojom/fetch_api.mojom
index 447ed9f..b66db3e 100644
--- a/services/network/public/mojom/fetch_api.mojom
+++ b/services/network/public/mojom/fetch_api.mojom
@@ -44,10 +44,10 @@
   kStyle = 16,
   kTrack = 17,
   kVideo = 18,
-  // kWebBundle represents a request for a WebBundle. A <link> element whose
-  // rel is "webbundle" uses this destination.
+  // kWebBundle represents a request for a WebBundle. A <script> element whose
+  // type is "webbundle" uses this destination.
   //
-  // e.g. <link rel=webbundle href="example.com/foo.wbn" resources="...">
+  // e.g. <script type=webbundle> { "source": "foo.wbn", ... } </script>
   //
   // Fetch specifiction does not define this destination yet.
   // Tracking issue: https://github.com/whatwg/fetch/issues/1120
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc
index bd5773a..4b0c20f 100644
--- a/services/network/url_loader_unittest.cc
+++ b/services/network/url_loader_unittest.cc
@@ -7324,6 +7324,8 @@
   EXPECT_TRUE(client_.response_head()->has_partitioned_cookie);
 }
 
+using ExtraHeaders = std::vector<std::pair<std::string, std::string>>;
+
 class URLLoaderCacheTransparencyTest : public URLLoaderTest {
  public:
   void SetUp() override {
@@ -7365,7 +7367,9 @@
     ResourceRequest request =
         CreateResourceRequest(method_.c_str(), test_server()->GetURL(path));
     request.load_flags = load_flags_;
-    request.headers.AddHeadersFromString(headers_);
+    for (const auto& [key, value] : headers_) {
+      request.headers.SetHeader(key, value);
+    }
 
     base::RunLoop delete_run_loop;
     mojo::Remote<mojom::URLLoader> loader;
@@ -7426,9 +7430,7 @@
 
   void set_load_flags(int flags) { load_flags_ = flags; }
 
-  // Headers are in the format accepted by
-  // HttpRequestHeaders::AddHeadersFromString(), ie. "\r\n" delimited.
-  void set_headers(std::string headers) { headers_ = std::move(headers); }
+  void set_headers(ExtraHeaders headers) { headers_ = std::move(headers); }
 
  private:
   static constexpr char kPervasivePayload[] = "/pervasive.js";
@@ -7443,7 +7445,7 @@
   bool third_party_cookies_enabled_ = true;
   std::string method_ = "GET";
   int load_flags_ = net::LOAD_NORMAL;
-  std::string headers_;
+  ExtraHeaders headers_;
   base::HistogramTester histogram_tester_;
 };
 
@@ -7484,7 +7486,8 @@
 }
 
 TEST_F(URLLoaderCacheTransparencyTest, IncompatibleHeaders) {
-  set_headers("Range: bytes=0-5\r\n");
+  ExtraHeaders headers = {{"Range", "bytes=0-5"}};
+  set_headers(headers);
   SendTwoRequestsWithDifferentOrigins();
   EXPECT_EQ(2, network_request_count());
   ExpectNotUsedReason(
diff --git a/services/network/web_bundle/web_bundle_manager_unittest.cc b/services/network/web_bundle/web_bundle_manager_unittest.cc
index af5658ba..d0c5400 100644
--- a/services/network/web_bundle/web_bundle_manager_unittest.cc
+++ b/services/network/web_bundle/web_bundle_manager_unittest.cc
@@ -241,16 +241,19 @@
   //
   // For example, given that we have the following main document:
   //
-  // <link rel=webbundle href="https://example.com/bundle.wbn"
-  // resources="https://example.com/a.txt">
-  // <img src="https://example.com/a.txt">  # Please ignore that a.txt is weird
-  // for <img>.
+  // <script type=webbundle>
+  //   {
+  //     "source": "bundle.wbn",
+  //     "resources": ["a.png", ...]
+  //   }
+  // </script>
+  // <img src="a.png">
   //
   // In this case, a network service should receive the following two resource
   // requests:
   //
   // 1. A request for a bundle, "bundle.wbn"
-  // 2. A request for a subresource, "a.txt".
+  // 2. A request for a subresource, "a.png".
   //
   // Usually, the request 1 arrives earlier than the request 2,
   // however, the arrival order is not guaranteed. The subresource should be
diff --git a/testing/android/junit/BUILD.gn b/testing/android/junit/BUILD.gn
index de9a7b4..e8065ca7 100644
--- a/testing/android/junit/BUILD.gn
+++ b/testing/android/junit/BUILD.gn
@@ -6,10 +6,7 @@
 
 import("//build/config/android/rules.gni")
 
-java_library("junit_test_support") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
-  testonly = true
+robolectric_library("junit_test_support") {
   sources = [
     "java/src/org/chromium/testing/local/CustomShadowApplicationPackageManager.java",
     "java/src/org/chromium/testing/local/GtestComputer.java",
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 1614959c9..216f751 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1773,7 +1773,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R104-14844.0.0",
+        "cros_img": "atlas-release/R104-14906.0.0",
         "name": "lacros_all_tast_tests ATLAS_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1805,7 +1805,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R103-14816.41.0",
+        "cros_img": "atlas-release/R103-14816.49.0",
         "name": "lacros_all_tast_tests ATLAS_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -1837,7 +1837,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R104-14844.0.0",
+        "cros_img": "eve-release/R104-14906.0.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1869,7 +1869,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R103-14816.41.0",
+        "cros_img": "eve-release/R103-14816.49.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -1946,7 +1946,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R104-14844.0.0",
+        "cros_img": "hana-release/R104-14906.0.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1978,7 +1978,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R103-14816.41.0",
+        "cros_img": "hana-release/R103-14816.49.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -2010,7 +2010,7 @@
       {
         "args": [],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R104-14844.0.0",
+        "cros_img": "jacuzzi-release/R104-14906.0.0",
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -2042,7 +2042,7 @@
       {
         "args": [],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R103-14816.41.0",
+        "cros_img": "jacuzzi-release/R103-14816.49.0",
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -2060,7 +2060,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.ozone_unittests.filter"
         ],
         "cros_board": "hana",
-        "cros_img": "hana-release/R104-14844.0.0",
+        "cros_img": "hana-release/R104-14906.0.0",
         "name": "ozone_unittests HANA_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -2086,7 +2086,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.ozone_unittests.filter"
         ],
         "cros_board": "hana",
-        "cros_img": "hana-release/R103-14816.41.0",
+        "cros_img": "hana-release/R103-14816.49.0",
         "name": "ozone_unittests HANA_RELEASE_BETA",
         "swarming": {},
         "test": "ozone_unittests",
@@ -2112,7 +2112,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.ozone_unittests.filter"
         ],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R104-14844.0.0",
+        "cros_img": "jacuzzi-release/R104-14906.0.0",
         "name": "ozone_unittests JACUZZI_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -2138,7 +2138,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.ozone_unittests.filter"
         ],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R103-14816.41.0",
+        "cros_img": "jacuzzi-release/R103-14816.49.0",
         "name": "ozone_unittests JACUZZI_RELEASE_BETA",
         "swarming": {},
         "test": "ozone_unittests",
@@ -2151,7 +2151,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.viz_unittests.filter"
         ],
         "cros_board": "hana",
-        "cros_img": "hana-release/R104-14844.0.0",
+        "cros_img": "hana-release/R104-14906.0.0",
         "name": "viz_unittests HANA_RELEASE_LKGM",
         "swarming": {},
         "test": "viz_unittests",
@@ -2177,7 +2177,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.viz_unittests.filter"
         ],
         "cros_board": "hana",
-        "cros_img": "hana-release/R103-14816.41.0",
+        "cros_img": "hana-release/R103-14816.49.0",
         "name": "viz_unittests HANA_RELEASE_BETA",
         "swarming": {},
         "test": "viz_unittests",
@@ -2203,7 +2203,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.viz_unittests.filter"
         ],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R104-14844.0.0",
+        "cros_img": "jacuzzi-release/R104-14906.0.0",
         "name": "viz_unittests JACUZZI_RELEASE_LKGM",
         "swarming": {},
         "test": "viz_unittests",
@@ -2229,7 +2229,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.viz_unittests.filter"
         ],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R103-14816.41.0",
+        "cros_img": "jacuzzi-release/R103-14816.49.0",
         "name": "viz_unittests JACUZZI_RELEASE_BETA",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/chromium.accessibility.json b/testing/buildbot/chromium.accessibility.json
index c1749ae..d1bda1e6 100644
--- a/testing/buildbot/chromium.accessibility.json
+++ b/testing/buildbot/chromium.accessibility.json
@@ -9,9 +9,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--flag-specific=force-renderer-accessibility"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 3f531d1..6494cee 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -8325,15 +8325,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8359,7 +8359,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.49"
+              "revision": "version:103.0.5060.50"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8410,15 +8410,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8444,7 +8444,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.6"
+              "revision": "version:104.0.5112.7"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8835,15 +8835,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8869,7 +8869,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.49"
+              "revision": "version:103.0.5060.50"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8920,15 +8920,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8954,7 +8954,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.6"
+              "revision": "version:104.0.5112.7"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index aa2d385..5679f25 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -46297,15 +46297,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46331,7 +46331,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.49"
+              "revision": "version:103.0.5060.50"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46382,15 +46382,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46416,7 +46416,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.6"
+              "revision": "version:104.0.5112.7"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46807,15 +46807,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46841,7 +46841,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.49"
+              "revision": "version:103.0.5060.50"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46892,15 +46892,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46926,7 +46926,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.6"
+              "revision": "version:104.0.5112.7"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47321,15 +47321,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47355,7 +47355,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.49"
+              "revision": "version:103.0.5060.50"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47406,15 +47406,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47440,7 +47440,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.6"
+              "revision": "version:104.0.5112.7"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47831,15 +47831,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47865,7 +47865,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.49"
+              "revision": "version:103.0.5060.50"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47916,15 +47916,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47950,7 +47950,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.6"
+              "revision": "version:104.0.5112.7"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48413,15 +48413,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48447,7 +48447,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.49"
+              "revision": "version:103.0.5060.50"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48498,15 +48498,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48532,7 +48532,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.6"
+              "revision": "version:104.0.5112.7"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48923,15 +48923,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48957,7 +48957,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.49"
+              "revision": "version:103.0.5060.50"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49008,15 +49008,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49042,7 +49042,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.6"
+              "revision": "version:104.0.5112.7"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49505,15 +49505,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49539,7 +49539,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.49"
+              "revision": "version:103.0.5060.50"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49590,15 +49590,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49624,7 +49624,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.6"
+              "revision": "version:104.0.5112.7"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50015,15 +50015,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50049,7 +50049,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.49"
+              "revision": "version:103.0.5060.50"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50100,15 +50100,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50134,7 +50134,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.6"
+              "revision": "version:104.0.5112.7"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 7590d86..ebec43d 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -10010,9 +10010,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--platform=fuchsia"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -23228,8 +23230,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -26816,8 +26820,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/chromium.dawn.json b/testing/buildbot/chromium.dawn.json
index dc344c2..1b6d5e2 100644
--- a/testing/buildbot/chromium.dawn.json
+++ b/testing/buildbot/chromium.dawn.json
@@ -222,6 +222,7 @@
           "--additional-driver-flag=--enable-features=Vulkan",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -546,6 +547,7 @@
           "--additional-driver-flag=--enable-features=Vulkan",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -907,6 +909,7 @@
           "--additional-driver-flag=--enable-features=Vulkan",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -1231,6 +1234,7 @@
           "--additional-driver-flag=--enable-features=Vulkan",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -1611,6 +1615,7 @@
           "--platform=mac-mac11",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -1942,6 +1947,7 @@
           "--platform=mac-mac11",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -2331,6 +2337,7 @@
           "--platform=mac-mac11",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -2714,6 +2721,7 @@
           "--platform=mac-mac11",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -3099,6 +3107,7 @@
           "--platform=mac-mac11",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -3430,6 +3439,7 @@
           "--platform=mac-mac11",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -3797,6 +3807,7 @@
           "--git-revision=${got_revision}",
           "--timeout-ms=48000"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -4088,6 +4099,7 @@
           "--target=Release_x64",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -4404,6 +4416,7 @@
           "--target=Release_x64",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -4757,6 +4770,7 @@
           "--target=Release_x64",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -5073,6 +5087,7 @@
           "--target=Release_x64",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -5400,6 +5415,7 @@
           "--initialize-webgpu-adapter-at-startup-timeout-ms=60000",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -5714,6 +5730,7 @@
           "--initialize-webgpu-adapter-at-startup-timeout-ms=60000",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -6038,6 +6055,7 @@
           "--initialize-webgpu-adapter-at-startup-timeout-ms=60000",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
@@ -6352,6 +6370,7 @@
           "--initialize-webgpu-adapter-at-startup-timeout-ms=60000",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "webgpu_blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/chromium.devtools-frontend.json b/testing/buildbot/chromium.devtools-frontend.json
index 4c18aa4..9274a83 100644
--- a/testing/buildbot/chromium.devtools-frontend.json
+++ b/testing/buildbot/chromium.devtools-frontend.json
@@ -29,8 +29,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/chromium.fuchsia.json b/testing/buildbot/chromium.fuchsia.json
index fede0b1..2aa393c 100644
--- a/testing/buildbot/chromium.fuchsia.json
+++ b/testing/buildbot/chromium.fuchsia.json
@@ -2503,10 +2503,12 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--platform=fuchsia",
           "--jobs=1"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 5338036..78938f2 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -5699,6 +5699,7 @@
           "--flag-specific=skia-vulkan-swiftshader",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -7231,8 +7232,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -86128,9 +86131,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--debug"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -86892,8 +86897,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -86931,8 +86938,10 @@
         "args": [
           "--flag-specific=highdpi",
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -87694,8 +87703,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -91078,9 +91089,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--additional-env-var=LLVM_PROFILE_FILE=${ISOLATED_OUTDIR}/profraw/default-%2m.profraw"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -91228,8 +91241,10 @@
         "args": [
           "--flag-specific=highdpi",
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -91286,9 +91301,11 @@
         "args": [
           "--flag-specific=disable-site-isolation-trials",
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--additional-env-var=LLVM_PROFILE_FILE=${ISOLATED_OUTDIR}/profraw/default-%2m.profraw"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -91429,6 +91446,7 @@
           "--flag-specific=skia-vulkan-swiftshader",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -100447,8 +100465,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -102704,8 +102724,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -102746,8 +102768,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -102786,8 +102810,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -102828,8 +102854,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -102868,8 +102896,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -106793,8 +106823,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -106832,10 +106864,12 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--target",
           "Release_x64"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index a790fda..984bce6 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -3555,9 +3555,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--additional-env-var=LLVM_PROFILE_FILE=${ISOLATED_OUTDIR}/profraw/default-%2m.profraw"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -3729,8 +3731,10 @@
         "args": [
           "--flag-specific=highdpi",
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -3787,9 +3791,11 @@
         "args": [
           "--flag-specific=disable-site-isolation-trials",
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--additional-env-var=LLVM_PROFILE_FILE=${ISOLATED_OUTDIR}/profraw/default-%2m.profraw"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -3956,6 +3962,7 @@
           "--flag-specific=skia-vulkan-swiftshader",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -7415,9 +7422,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--debug"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -7757,10 +7766,12 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--flag-specific=enable-back-forward-cache-same-site",
           "--ignore-tests=external/wpt/html/browsers/browsing-the-web/back-forward-cache/events.html"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 3a6759c..4f65547a 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -1480,8 +1480,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -3235,8 +3237,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -4998,8 +5002,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -6837,8 +6843,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -8635,9 +8643,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--debug"
         ],
+        "check_flakiness_for_new_tests": false,
         "experiment_percentage": 100,
         "isolate_name": "blink_web_tests",
         "merge": {
@@ -20864,8 +20874,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "ci_only": true,
         "isolate_name": "blink_web_tests",
         "merge": {
@@ -22652,8 +22664,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "ci_only": true,
         "isolate_name": "blink_web_tests",
         "merge": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 9932781..0883ed1 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -12447,6 +12447,7 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--additional-expectations",
           "../../third_party/blink/web_tests/ASANExpectations",
@@ -12454,6 +12455,7 @@
           "48000",
           "--enable-sanitizer"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -12493,6 +12495,7 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--additional-expectations",
           "../../third_party/blink/web_tests/LeakExpectations",
@@ -12500,6 +12503,7 @@
           "48000",
           "--enable-leak-detection"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -12536,6 +12540,7 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--additional-expectations",
           "../../third_party/blink/web_tests/MSANExpectations",
@@ -12543,6 +12548,7 @@
           "66000",
           "--enable-sanitizer"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 4879df7..48c7abd 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -6,8 +6,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -4120,10 +4122,12 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--target",
           "Release_x64"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "isolate_profile_data": true,
         "merge": {
@@ -8521,10 +8525,12 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--target",
           "Release_x64"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "isolate_profile_data": true,
         "merge": {
diff --git a/testing/buildbot/client.devtools-frontend.integration.json b/testing/buildbot/client.devtools-frontend.integration.json
index b45d3b7..b49abd6 100644
--- a/testing/buildbot/client.devtools-frontend.integration.json
+++ b/testing/buildbot/client.devtools-frontend.integration.json
@@ -50,8 +50,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -162,8 +164,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/client.v8.fyi.json b/testing/buildbot/client.v8.fyi.json
index 5947391..3f66756 100644
--- a/testing/buildbot/client.v8.fyi.json
+++ b/testing/buildbot/client.v8.fyi.json
@@ -1460,8 +1460,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -1521,11 +1523,13 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "-t",
           "Debug",
           "--release"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -1585,9 +1589,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--flag-specific=future-js"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -1648,8 +1654,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -1690,8 +1698,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index 37d4d60..732bf4d 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1038,7 +1038,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R104-14844.0.0",
+        "cros_img": "octopus-release/R104-14906.0.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational || \"name:lacros.VariationSmoke\")",
@@ -1062,7 +1062,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R103-14816.41.0",
+        "cros_img": "octopus-release/R103-14816.49.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_BETA",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational || \"name:lacros.VariationSmoke\")",
@@ -1086,7 +1086,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R104-14844.0.0",
+        "cros_img": "octopus-release/R104-14906.0.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1108,7 +1108,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R103-14816.41.0",
+        "cros_img": "octopus-release/R103-14816.49.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_BETA",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1138,7 +1138,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14844.0.0",
+        "cros_img": "strongbad-release/R104-14906.0.0",
         "name": "lacros_all_tast_tests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1186,7 +1186,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14844.0.0",
+        "cros_img": "strongbad-release/R104-14906.0.0",
         "name": "ozone_unittests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1230,7 +1230,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14844.0.0",
+        "cros_img": "strongbad-release/R104-14906.0.0",
         "name": "viz_unittests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 24e28d79..c12127e 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -389,6 +389,9 @@
       ],
     },
   },
+  'disable_check_flakiness_web_tests': {
+     'check_flakiness_for_new_tests': False,
+  },
   'disable_field_trial_config_for_earl_grey': {
     '$mixin_append': {
       'args': [
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index d930cb8..5bbb5b0 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -602,10 +602,12 @@
         'args': [
           '--test-type=integration',
         ],
-        'check_flakiness_for_new_tests': False,
         'resultdb': {
           'enable': True,
         },
+        'mixins': [
+          'disable_check_flakiness_web_tests',
+        ],
       },
       'chromedriver_replay_unittests': {},
     },
@@ -1235,6 +1237,7 @@
         # retry 3 times, so we explicitly specify it.
         'args': [
           '--num-retries=3',
+          '--fuzzy-diff',
         ],
         'isolate_name': 'blink_web_tests',
         'merge': {
@@ -1244,6 +1247,8 @@
           'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
         'mixins': [
+           # TODO(crbug.com/1327314): Enable for blink web tests.
+          'disable_check_flakiness_web_tests',
           'skia_gold_test',
         ],
         'resultdb': {
@@ -1279,6 +1284,7 @@
           # passed, but 0 times when '--test-list' is passed. We want to always
           # retry 3 times, so we explicitly specify it.
           '--num-retries=3',
+          '--fuzzy-diff',
         ],
         'isolate_name': 'blink_web_tests',
         'merge': {
@@ -1288,6 +1294,8 @@
           'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
         'mixins': [
+          # TODO(crbug.com/1327314): Enable for blink web tests.
+          'disable_check_flakiness_web_tests',
           'skia_gold_test',
         ],
         'resultdb': {
@@ -1307,6 +1315,7 @@
         # retry 3 times, so we explicitly specify it.
         'args': [
           '--num-retries=3',
+          '--fuzzy-diff',
         ],
         'isolate_name': 'blink_web_tests',
         'merge': {
@@ -1316,6 +1325,8 @@
           'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
         'mixins': [
+          # TODO(crbug.com/1327314): Enable for blink web tests.
+          'disable_check_flakiness_web_tests',
           'skia_gold_test',
         ],
         'resultdb': {
@@ -1528,6 +1539,7 @@
         # retry 3 times, so we explicitly specify it.
         'args': [
           '--num-retries=3',
+          '--fuzzy-diff',
         ],
         'isolate_name': 'blink_web_tests',
         'merge': {
@@ -1537,6 +1549,8 @@
           'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
         'mixins': [
+          # TODO(crbug.com/1327314): Enable for blink web tests.
+          'disable_check_flakiness_web_tests',
           'skia_gold_test',
         ],
         'resultdb': {
@@ -1619,6 +1633,7 @@
         # retry 3 times, so we explicitly specify it.
         'args': [
           '--num-retries=3',
+          '--fuzzy-diff',
         ],
         'isolate_name': 'blink_web_tests',
         'merge': {
@@ -1628,6 +1643,8 @@
           'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
         'mixins': [
+          # TODO(crbug.com/1327314): Enable for blink web tests.
+          'disable_check_flakiness_web_tests',
           'skia_gold_test',
         ],
         'resultdb': {
@@ -3716,6 +3733,8 @@
           '--flag-specific=webgpu',
         ],
         'mixins': [
+          # TODO(crbug.com/1327314): Enable for blink web tests.
+          'disable_check_flakiness_web_tests',
           'webgpu_cts',
           'skia_gold_test',
         ],
@@ -4191,6 +4210,7 @@
           # passed, but 0 times when '--test-list' is passed. We want to always
           # retry 3 times, so we explicitly specify it.
           '--num-retries=3',
+          '--fuzzy-diff',
         ],
         'isolate_name': 'blink_web_tests',
         'merge': {
@@ -4200,6 +4220,8 @@
           'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
         'mixins': [
+          # TODO(crbug.com/1327314): Enable for blink web tests.
+          'disable_check_flakiness_web_tests',
           'skia_gold_test',
         ],
         'resultdb': {
@@ -4872,11 +4894,13 @@
           '--passthrough',
           '--retry-limit=2',
         ],
-        'check_flakiness_for_new_tests': False,
         'isolate_name': 'telemetry_perf_unittests_android_chrome',
         'resultdb': {
           'enable': True,
         },
+        'mixins': [
+          'disable_check_flakiness_web_tests',
+        ],
       },
       'telemetry_monochrome_minidump_unittests': {
         'args': [
@@ -4902,11 +4926,13 @@
           '--passthrough',
           '--retry-limit=2',
         ],
-        'check_flakiness_for_new_tests': False,
         'isolate_name': 'telemetry_perf_unittests',
         'resultdb': {
           'enable': True,
         },
+        'mixins': [
+          'disable_check_flakiness_web_tests',
+        ],
       },
     },
 
@@ -5096,6 +5122,8 @@
           'script': '//third_party/blink/tools/merge_web_test_results.py',
         },
         'mixins': [
+          # TODO(crbug.com/1327314): Enable for blink web tests.
+          'disable_check_flakiness_web_tests',
           'skia_gold_test',
         ],
         'resultdb': {
diff --git a/testing/buildbot/tryserver.blink.json b/testing/buildbot/tryserver.blink.json
index 4bd0736..c7ce8e8 100644
--- a/testing/buildbot/tryserver.blink.json
+++ b/testing/buildbot/tryserver.blink.json
@@ -6,8 +6,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -65,8 +67,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -104,8 +108,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/tryserver.chromium.linux.json b/testing/buildbot/tryserver.chromium.linux.json
index 231a1a6..d0edd7d3 100644
--- a/testing/buildbot/tryserver.chromium.linux.json
+++ b/testing/buildbot/tryserver.chromium.linux.json
@@ -14,9 +14,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--flag-specific=enable-editing-ng"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -80,9 +82,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "--flag-specific=disable-layout-ng"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/tryserver.devtools-frontend.json b/testing/buildbot/tryserver.devtools-frontend.json
index b4385ec..5641853 100644
--- a/testing/buildbot/tryserver.devtools-frontend.json
+++ b/testing/buildbot/tryserver.devtools-frontend.json
@@ -29,9 +29,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "http/tests/devtools"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -121,9 +123,11 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}",
           "http/tests/devtools"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
@@ -190,8 +194,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/tryserver.v8.json b/testing/buildbot/tryserver.v8.json
index 468894e..e0db3041 100644
--- a/testing/buildbot/tryserver.v8.json
+++ b/testing/buildbot/tryserver.v8.json
@@ -6,8 +6,10 @@
       {
         "args": [
           "--num-retries=3",
+          "--fuzzy-diff",
           "--git-revision=${got_revision}"
         ],
+        "check_flakiness_for_new_tests": false,
         "isolate_name": "blink_web_tests",
         "merge": {
           "args": [
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 00dc4a78..514dd049 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -462,16 +462,16 @@
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M104/out/Release',
-      '--impl-version=104'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=104',
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -479,23 +479,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.6'
+          'revision': 'version:104.0.5112.7',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M103/out/Release',
-      '--impl-version=103'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=103',
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -503,10 +503,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.49'
+          'revision': 'version:103.0.5060.50',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -606,16 +606,16 @@
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M104/out/Release',
-      '--impl-version=104'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=104',
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -623,23 +623,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.6'
+          'revision': 'version:104.0.5112.7',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M103/out/Release',
-      '--impl-version=103'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=103',
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -647,10 +647,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.49'
+          'revision': 'version:103.0.5060.50',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -750,16 +750,16 @@
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M104/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M104/out/Release',
-      '--client-version=104'
+      '--client-version=104',
     ],
     'identifier': 'with_client_from_104',
     'swarming': {
@@ -767,23 +767,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.6'
+          'revision': 'version:104.0.5112.7',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
-      '--client-version=103'
+      '--client-version=103',
     ],
     'identifier': 'with_client_from_103',
     'swarming': {
@@ -791,10 +791,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.49'
+          'revision': 'version:103.0.5060.50',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -895,8 +895,8 @@
   'CROS_ATLAS_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_chrome_version': '104.0.5065.0',
-      'cros_img': 'atlas-release/R104-14844.0.0',
+      'cros_chrome_version': '104.0.5087.0',
+      'cros_img': 'atlas-release/R104-14906.0.0',
     },
     'enabled': True,
     'identifier': 'ATLAS_RELEASE_LKGM',
@@ -913,8 +913,8 @@
   'CROS_ATLAS_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_chrome_version': '103.0.5060.33',
-      'cros_img': 'atlas-release/R103-14816.41.0',
+      'cros_chrome_version': '103.0.5060.37',
+      'cros_img': 'atlas-release/R103-14816.49.0',
     },
     'enabled': True,
     'identifier': 'ATLAS_RELEASE_BETA',
@@ -931,8 +931,8 @@
   'CROS_EVE_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '104.0.5065.0',
-      'cros_img': 'eve-release/R104-14844.0.0',
+      'cros_chrome_version': '104.0.5087.0',
+      'cros_img': 'eve-release/R104-14906.0.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_LKGM',
@@ -949,8 +949,8 @@
   'CROS_EVE_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '103.0.5060.33',
-      'cros_img': 'eve-release/R103-14816.41.0',
+      'cros_chrome_version': '103.0.5060.37',
+      'cros_img': 'eve-release/R103-14816.49.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_BETA',
@@ -976,8 +976,8 @@
   'CROS_HANA_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'hana',
-      'cros_chrome_version': '104.0.5065.0',
-      'cros_img': 'hana-release/R104-14844.0.0',
+      'cros_chrome_version': '104.0.5087.0',
+      'cros_img': 'hana-release/R104-14906.0.0',
     },
     'enabled': True,
     'identifier': 'HANA_RELEASE_LKGM',
@@ -994,8 +994,8 @@
   'CROS_HANA_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'hana',
-      'cros_chrome_version': '103.0.5060.33',
-      'cros_img': 'hana-release/R103-14816.41.0',
+      'cros_chrome_version': '103.0.5060.37',
+      'cros_img': 'hana-release/R103-14816.49.0',
     },
     'enabled': True,
     'identifier': 'HANA_RELEASE_BETA',
@@ -1012,8 +1012,8 @@
   'CROS_JACUZZI_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'jacuzzi',
-      'cros_chrome_version': '104.0.5065.0',
-      'cros_img': 'jacuzzi-release/R104-14844.0.0',
+      'cros_chrome_version': '104.0.5087.0',
+      'cros_img': 'jacuzzi-release/R104-14906.0.0',
     },
     'enabled': True,
     'identifier': 'JACUZZI_RELEASE_LKGM',
@@ -1030,8 +1030,8 @@
   'CROS_JACUZZI_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'jacuzzi',
-      'cros_chrome_version': '103.0.5060.33',
-      'cros_img': 'jacuzzi-release/R103-14816.41.0',
+      'cros_chrome_version': '103.0.5060.37',
+      'cros_img': 'jacuzzi-release/R103-14816.49.0',
     },
     'enabled': True,
     'identifier': 'JACUZZI_RELEASE_BETA',
@@ -1048,8 +1048,8 @@
   'CROS_OCTOPUS_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '104.0.5065.0',
-      'cros_img': 'octopus-release/R104-14844.0.0',
+      'cros_chrome_version': '104.0.5087.0',
+      'cros_img': 'octopus-release/R104-14906.0.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_LKGM',
@@ -1066,8 +1066,8 @@
   'CROS_OCTOPUS_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '103.0.5060.33',
-      'cros_img': 'octopus-release/R103-14816.41.0',
+      'cros_chrome_version': '103.0.5060.37',
+      'cros_img': 'octopus-release/R103-14816.49.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_BETA',
@@ -1084,8 +1084,8 @@
   'CROS_STRONGBAD_RELEASE_LKGM': {
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_chrome_version': '104.0.5065.0',
-      'cros_img': 'strongbad-release/R104-14844.0.0',
+      'cros_chrome_version': '104.0.5087.0',
+      'cros_img': 'strongbad-release/R104-14906.0.0',
     },
     'enabled': True,
     'identifier': 'STRONGBAD_RELEASE_LKGM',
@@ -1161,4 +1161,4 @@
       'win10_nvidia_gtx_1660_stable',
     ],
   },
-}
+}
\ No newline at end of file
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 79b52614..519a360 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -8941,6 +8941,21 @@
                     "min_os_version": "10.0.0"
                 }
             ]
+        },
+        {
+            "platforms": [
+                "linux"
+            ],
+            "experiments": [
+                {
+                    "name": "Vulkan",
+                    "enable_features": [
+                        "DefaultANGLEVulkan",
+                        "Vulkan",
+                        "VulkanFromANGLE"
+                    ]
+                }
+            ]
         }
     ],
     "WebApkServiceWorkerRemovalStudy": [
diff --git a/third_party/android_deps/BUILD.gn b/third_party/android_deps/BUILD.gn
index b0ca38b3..d398bccf 100644
--- a/third_party/android_deps/BUILD.gn
+++ b/third_party/android_deps/BUILD.gn
@@ -30,10 +30,6 @@
   java_group("robolectric_all_java") {
     testonly = true
 
-    # Prevent 'gn format' from sorting deps. In order for the classpath to be
-    # correct, newer robolectric android-all versions should be listed below older
-    # versions.
-    # NOSORT
     deps = [
       ":org_robolectric_annotations_java",
       ":org_robolectric_junit_java",
@@ -48,9 +44,12 @@
       ":org_robolectric_shadows_playservices_java",
       ":org_robolectric_utils_java",
       ":org_robolectric_utils_reflector_java",
+    ]
 
-      "//third_party/robolectric:robolectric_runtime_jars",
-      "//third_party/robolectric:android-all-10-robolectric-5803371_java",
+    # Temporarily keep compiling against robolectric until every target is
+    # migarated to robolectric_library. See https://crbug.com/1296632
+    input_jars_paths = [
+      "//third_party/robolectric/lib/android-all-12-robolectric-7732740.jar",
     ]
   }
 
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index 3f7c022..35d870a 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -1058,8 +1058,6 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_context_state.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_playback_destination.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_audio_playback_destination.h",
-  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authenticator_attachment.cc",
-  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_authenticator_attachment.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_automation_rate.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_automation_rate.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_avc_bitstream_format.cc",
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 14fc429..17850e0 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -586,7 +586,7 @@
 }
 
 static bool AcceptsEditingFocus(const Element& element) {
-  DCHECK(HasEditableStyle(element));
+  DCHECK(IsEditable(element));
 
   return element.GetDocument().GetFrame() && RootEditableElement(element);
 }
@@ -6451,9 +6451,6 @@
   // Always return a null URL when passed a null string.
   // FIXME: Should we change the KURL constructor to have this behavior?
   // See also [CSS]StyleSheet::completeURL(const String&)
-  // TODO(crbug.com/1244483): Make sure that LinkWebBundle::CompleteURL
-  // implementation stays in line with this one (disregarding the encoding
-  // part).
   if (url.IsNull())
     return KURL();
   if (!Encoding().IsValid())
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index c234542..4f61d4c 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -6831,7 +6831,7 @@
 }
 
 bool Element::MayTriggerVirtualKeyboard() const {
-  return HasEditableStyle(*this);
+  return IsEditable(*this);
 }
 
 bool Element::matches(const AtomicString& selectors,
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc
index 2b9feb8..9fe3807 100644
--- a/third_party/blink/renderer/core/dom/node.cc
+++ b/third_party/blink/renderer/core/dom/node.cc
@@ -1667,7 +1667,7 @@
 bool Node::CanStartSelection() const {
   if (DisplayLockUtilities::LockedAncestorPreventingPaint(*this))
     GetDocument().UpdateStyleAndLayoutTreeForNode(this);
-  if (HasEditableStyle(*this))
+  if (IsEditable(*this))
     return true;
 
   if (GetLayoutObject()) {
@@ -1693,7 +1693,7 @@
       << GetDocument().Lifecycle().ToString();
 #endif  // DCHECK_IS_ON()
 
-  return HasRichlyEditableStyle(*this);
+  return IsRichlyEditable(*this);
 }
 
 void Node::NotifyPriorityScrollAnchorStatusChanged() {
@@ -2326,7 +2326,7 @@
   DumpAttributeDesc(*this, html_names::kIdAttr, builder);
   DumpAttributeDesc(*this, html_names::kClassAttr, builder);
   DumpAttributeDesc(*this, html_names::kStyleAttr, builder);
-  if (HasEditableStyle(*this))
+  if (IsEditable(*this))
     builder.Append(" (editable)");
   if (GetDocument().FocusedElement() == this)
     builder.Append(" (focused)");
@@ -3050,7 +3050,7 @@
   if (IsDisabledFormControl(this))
     return false;
   GetDocument().UpdateStyleAndLayoutTree();
-  return HasEditableStyle(*this) ||
+  return IsEditable(*this) ||
          HasAnyEventListeners(event_util::MouseButtonEventTypes());
 }
 
diff --git a/third_party/blink/renderer/core/editing/commands/append_node_command.cc b/third_party/blink/renderer/core/editing/commands/append_node_command.cc
index baa0db5..375fb853 100644
--- a/third_party/blink/renderer/core/editing/commands/append_node_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/append_node_command.cc
@@ -36,18 +36,18 @@
   DCHECK(node_);
   DCHECK(!node_->parentNode()) << node_;
 
-  DCHECK(HasEditableStyle(*parent_) || !parent_->InActiveDocument()) << parent_;
+  DCHECK(IsEditable(*parent_) || !parent_->InActiveDocument()) << parent_;
 }
 
 void AppendNodeCommand::DoApply(EditingState*) {
-  if (!HasEditableStyle(*parent_) && parent_->InActiveDocument())
+  if (!IsEditable(*parent_) && parent_->InActiveDocument())
     return;
 
   parent_->AppendChild(node_.Get(), IGNORE_EXCEPTION_FOR_TESTING);
 }
 
 void AppendNodeCommand::DoUnapply() {
-  if (!HasEditableStyle(*parent_))
+  if (!IsEditable(*parent_))
     return;
 
   node_->remove(IGNORE_EXCEPTION_FOR_TESTING);
diff --git a/third_party/blink/renderer/core/editing/commands/apply_style_command.cc b/third_party/blink/renderer/core/editing/commands/apply_style_command.cc
index 10e1baf6..3fbfb868 100644
--- a/third_party/blink/renderer/core/editing/commands/apply_style_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/apply_style_command.cc
@@ -909,14 +909,14 @@
 }
 
 static bool ContainsNonEditableRegion(Node& node) {
-  if (!HasEditableStyle(node))
+  if (!IsEditable(node))
     return true;
 
   Node* sibling = NodeTraversal::NextSkippingChildren(node);
   for (Node* descendent = node.firstChild();
        descendent && descendent != sibling;
        descendent = NodeTraversal::Next(*descendent)) {
-    if (!HasEditableStyle(*descendent))
+    if (!IsEditable(*descendent))
       return true;
   }
 
@@ -976,11 +976,11 @@
   for (Node* next; node && node != past_end_node; node = next) {
     next = NodeTraversal::Next(*node);
 
-    if (!node->GetLayoutObject() || !HasEditableStyle(*node))
+    if (!node->GetLayoutObject() || !IsEditable(*node))
       continue;
 
     auto* element = DynamicTo<HTMLElement>(node);
-    if (!HasRichlyEditableStyle(*node) && element) {
+    if (!IsRichlyEditable(*node) && element) {
       // This is a plaintext-only region. Only proceed if it's fully selected.
       // pastEndNode is the node after the last fully selected node, so if it's
       // inside node then node isn't fully selected.
@@ -1003,7 +1003,7 @@
 
     if (node->hasChildren()) {
       if (node->contains(past_end_node) || ContainsNonEditableRegion(*node) ||
-          !HasEditableStyle(*node->parentNode()))
+          !IsEditable(*node->parentNode()))
         continue;
       if (EditingIgnoresContent(*node)) {
         next = NodeTraversal::NextSkippingChildren(*node);
@@ -1146,7 +1146,7 @@
     EditingStyle* extracted_style) {
   DCHECK(element);
   GetDocument().UpdateStyleAndLayoutTree();
-  if (!element->parentNode() || !HasEditableStyle(*element->parentNode()))
+  if (!element->parentNode() || !IsEditable(*element->parentNode()))
     return false;
 
   if (IsStyledInlineElementToRemove(element)) {
@@ -1776,7 +1776,7 @@
   GetDocument().UpdateStyleAndLayoutTree();
   while (node) {
     Node* next = node->nextSibling();
-    if (HasEditableStyle(*node)) {
+    if (IsEditable(*node)) {
       RemoveNode(node, editing_state);
       if (editing_state->IsAborted())
         return;
@@ -1792,7 +1792,7 @@
   Node* next_sibling = element->nextSibling();
   Node* previous_sibling = element->previousSibling();
   auto* next_sibling_element = DynamicTo<Element>(next_sibling);
-  if (next_sibling_element && HasEditableStyle(*next_sibling) &&
+  if (next_sibling_element && IsEditable(*next_sibling) &&
       AreIdenticalElements(*element, *next_sibling_element)) {
     MergeIdenticalElements(element, next_sibling_element, editing_state);
     if (editing_state->IsAborted())
@@ -1800,10 +1800,9 @@
   }
 
   auto* previous_sibling_element = DynamicTo<Element>(previous_sibling);
-  if (previous_sibling_element && HasEditableStyle(*previous_sibling)) {
+  if (previous_sibling_element && IsEditable(*previous_sibling)) {
     auto* merged_element = DynamicTo<Element>(previous_sibling->nextSibling());
-    if (merged_element &&
-        HasEditableStyle(*(previous_sibling->nextSibling())) &&
+    if (merged_element && IsEditable(*(previous_sibling->nextSibling())) &&
         AreIdenticalElements(*previous_sibling_element, *merged_element)) {
       MergeIdenticalElements(previous_sibling_element, merged_element,
                              editing_state);
diff --git a/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc b/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
index da0753d6..d89c1a7 100644
--- a/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
+++ b/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
@@ -282,7 +282,7 @@
   const Node& start_container = *range.StartPosition().ComputeContainerNode();
   const Node& end_container = *range.EndPosition().ComputeContainerNode();
 
-  return HasEditableStyle(start_container) && HasEditableStyle(end_container);
+  return IsEditable(start_container) && IsEditable(end_container);
 }
 
 static DeleteMode ConvertSmartReplaceOptionToDeleteMode(
diff --git a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
index 3e2f8222..63958439 100644
--- a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
@@ -298,7 +298,7 @@
   // TODO(editing-dev): Use of UpdateStyleAndLayout
   // needs to be audited.  See http://crbug.com/590369 for more details.
   GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
-  ABORT_EDITING_COMMAND_IF(!HasEditableStyle(*ref_child->parentNode()) &&
+  ABORT_EDITING_COMMAND_IF(!IsEditable(*ref_child->parentNode()) &&
                            ref_child->parentNode()->InActiveDocument());
   ApplyCommandToComposite(
       MakeGarbageCollected<InsertNodeBeforeCommand>(
@@ -375,8 +375,7 @@
   ABORT_EDITING_COMMAND_IF(!CanHaveChildrenForEditing(parent) &&
                            !(parent_element && parent_element->TagQName() ==
                                                    html_names::kObjectTag));
-  ABORT_EDITING_COMMAND_IF(!HasEditableStyle(*parent) &&
-                           parent->InActiveDocument());
+  ABORT_EDITING_COMMAND_IF(!IsEditable(*parent) && parent->InActiveDocument());
   ApplyCommandToComposite(MakeGarbageCollected<AppendNodeCommand>(parent, node),
                           editing_state);
 }
@@ -692,8 +691,9 @@
 
   auto* text_node = DynamicTo<Text>(position.ComputeContainerNode());
   if (!position.IsOffsetInAnchor() || !text_node ||
-      !HasRichlyEditableStyle(*text_node))
+      !IsRichlyEditable(*text_node)) {
     return false;
+  }
 
   if (text_node->length() == 0)
     return false;
@@ -1694,7 +1694,7 @@
   if (!list_node ||
       (!IsA<HTMLUListElement>(*list_node) &&
        !IsA<HTMLOListElement>(*list_node)) ||
-      !HasEditableStyle(*list_node) ||
+      !IsEditable(*list_node) ||
       list_node == RootEditableElement(*empty_list_item))
     return false;
 
diff --git a/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc b/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc
index 1a2209a9..2360fdc 100644
--- a/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc
@@ -47,7 +47,7 @@
   DCHECK(node_);
 
   GetDocument().UpdateStyleAndLayoutTree();
-  if (!HasEditableStyle(*node_))
+  if (!IsEditable(*node_))
     return;
 
   DummyExceptionStateForTesting exception_state;
@@ -61,7 +61,7 @@
 void DeleteFromTextNodeCommand::DoUnapply() {
   DCHECK(node_);
 
-  if (!HasEditableStyle(*node_))
+  if (!IsEditable(*node_))
     return;
 
   node_->insertData(offset_, text_, IGNORE_EXCEPTION_FOR_TESTING);
diff --git a/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc b/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
index 7327187..8b5a2c1 100644
--- a/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
@@ -477,7 +477,7 @@
 static Position FirstEditablePositionInNode(Node* node) {
   DCHECK(node);
   Node* next = node;
-  while (next && !HasEditableStyle(*next))
+  while (next && !IsEditable(*next))
     next = NodeTraversal::Next(*next, node);
   return next ? FirstPositionInOrBeforeNode(*next) : Position();
 }
@@ -494,7 +494,7 @@
                                     node->IsDescendantOf(end_root_.Get()))) {
     // If a node is not in both the start and end editable roots, remove it only
     // if its inside an editable region.
-    if (!HasEditableStyle(*node->parentNode())) {
+    if (!IsEditable(*node->parentNode())) {
       // Don't remove non-editable atomic nodes.
       if (!node->hasChildren())
         return;
@@ -625,7 +625,7 @@
           node_to_be_removed->IsDescendantOf(end_root_.Get()))) {
       // If a node is not in both the start and end editable roots, remove it
       // only if its inside an editable region.
-      if (!HasEditableStyle(*node_to_be_removed->parentNode())) {
+      if (!IsEditable(*node_to_be_removed->parentNode())) {
         // Don't remove non-editable atomic nodes.
         if (!node_to_be_removed->hasChildren())
           continue;
diff --git a/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc b/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc
index b0b9b11..3503baf0 100644
--- a/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc
+++ b/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc
@@ -132,7 +132,7 @@
       SetSelectionTextToBody(
           "^<style>body{-webkit-user-modify:read-write}</style>x|"),
       SetSelectionOptions());
-  EXPECT_TRUE(HasEditableStyle(*GetDocument().body()));
+  EXPECT_TRUE(IsEditable(*GetDocument().body()));
 
   DeleteSelectionCommand& command =
       *MakeGarbageCollected<DeleteSelectionCommand>(
@@ -145,7 +145,7 @@
 
   // The command removes the <style>, so the <body> stops being editable,
   // and then "x" is not removed.
-  EXPECT_FALSE(HasEditableStyle(*GetDocument().body()));
+  EXPECT_FALSE(IsEditable(*GetDocument().body()));
   EXPECT_EQ("|x", GetSelectionTextFromBody());
 }
 
diff --git a/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc b/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc
index 81f94f04..ad61bcdd 100644
--- a/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc
+++ b/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc
@@ -141,7 +141,7 @@
   if (!first_element->HasEquivalentAttributes(*second_element))
     return false;
 
-  return HasEditableStyle(*first_element) && HasEditableStyle(*second_element);
+  return IsEditable(*first_element) && IsEditable(*second_element);
 }
 
 // FIXME: need to dump this
@@ -426,8 +426,8 @@
   return first_list.HasTagName(
              second_list
                  .TagQName())  // make sure the list types match (ol vs. ul)
-         && HasEditableStyle(first_list) &&
-         HasEditableStyle(second_list)  // both lists are editable
+         && IsEditable(first_list) &&
+         IsEditable(second_list)  // both lists are editable
          &&
          RootEditableElement(first_list) ==
              RootEditableElement(second_list)  // don't cross editing boundaries
@@ -507,12 +507,11 @@
 // which assumes a document has a valid HTML structure. We should make the
 // editing code more robust, and should remove this hack. crbug.com/580941.
 void TidyUpHTMLStructure(Document& document) {
-  // hasEditableStyle() needs up-to-date ComputedStyle.
+  // IsEditable() needs up-to-date ComputedStyle.
   document.UpdateStyleAndLayoutTree();
   const bool needs_valid_structure =
-      HasEditableStyle(document) ||
-      (document.documentElement() &&
-       HasEditableStyle(*document.documentElement()));
+      IsEditable(document) ||
+      (document.documentElement() && IsEditable(*document.documentElement()));
   if (!needs_valid_structure)
     return;
 
diff --git a/third_party/blink/renderer/core/editing/commands/editor_command.cc b/third_party/blink/renderer/core/editing/commands/editor_command.cc
index 32e48faf..bc1062a6 100644
--- a/third_party/blink/renderer/core/editing/commands/editor_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/editor_command.cc
@@ -2064,7 +2064,7 @@
 
 const StaticRangeVector* EditorCommand::GetTargetRanges() const {
   const Node* target = EventTargetNodeForDocument(frame_->GetDocument());
-  if (!IsSupported() || !frame_ || !target || !HasRichlyEditableStyle(*target))
+  if (!IsSupported() || !frame_ || !target || !IsRichlyEditable(*target))
     return nullptr;
 
   switch (command_->command_type) {
diff --git a/third_party/blink/renderer/core/editing/commands/format_block_command.cc b/third_party/blink/renderer/core/editing/commands/format_block_command.cc
index 5cecaf6..69c3403 100644
--- a/third_party/blink/renderer/core/editing/commands/format_block_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/format_block_command.cc
@@ -193,17 +193,16 @@
   DCHECK(start_node);
   Node* last_block = start_node;
   for (Node& runner : NodeTraversal::InclusiveAncestorsOf(*start_node)) {
-    if (!HasEditableStyle(runner))
+    if (!IsEditable(runner))
       return last_block;
     if (IsTableCell(&runner) || IsA<HTMLBodyElement>(&runner) ||
-        !runner.parentNode() || !HasEditableStyle(*runner.parentNode()) ||
+        !runner.parentNode() || !IsEditable(*runner.parentNode()) ||
         IsElementForFormatBlock(&runner))
       return &runner;
     if (IsEnclosingBlock(&runner))
       last_block = &runner;
     if (IsHTMLListElement(&runner))
-      return HasEditableStyle(*runner.parentNode()) ? runner.parentNode()
-                                                    : &runner;
+      return IsEditable(*runner.parentNode()) ? runner.parentNode() : &runner;
   }
   return last_block;
 }
diff --git a/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc b/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc
index 856882b..c678694 100644
--- a/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc
@@ -257,7 +257,7 @@
       EnclosingNodeOfType(visible_start_of_paragraph.DeepEquivalent(),
                           &IsHTMLListOrBlockquoteElement));
   // We can't outdent if there is no place to go!
-  if (!enclosing_element || !HasEditableStyle(*enclosing_element->parentNode()))
+  if (!enclosing_element || !IsEditable(*enclosing_element->parentNode()))
     return;
 
   // Use InsertListCommand to remove the selection from the list
@@ -316,7 +316,7 @@
         // We can't outdent if there is no place to go!
         if (split_point_parent->HasTagName(html_names::kBlockquoteTag) &&
             !split_point->HasTagName(html_names::kBlockquoteTag) &&
-            HasEditableStyle(*split_point_parent->parentNode()))
+            IsEditable(*split_point_parent->parentNode()))
           SplitElement(split_point_parent, split_point);
       }
     }
diff --git a/third_party/blink/renderer/core/editing/commands/insert_commands.cc b/third_party/blink/renderer/core/editing/commands/insert_commands.cc
index 78b6c251..a0b3eda 100644
--- a/third_party/blink/renderer/core/editing/commands/insert_commands.cc
+++ b/third_party/blink/renderer/core/editing/commands/insert_commands.cc
@@ -134,7 +134,7 @@
   } else {
     if (Node* anchor =
             frame.Selection().GetSelectionInDOMTree().Base().AnchorNode()) {
-      if (HasEditableStyle(*anchor) && !HasRichlyEditableStyle(*anchor)) {
+      if (IsEditable(*anchor) && !IsRichlyEditable(*anchor)) {
         UseCounter::Count(frame.GetDocument(),
                           WebFeature::kInsertHTMLCommandOnReadWritePlainText);
       }
diff --git a/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc b/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc
index c423f98..d0de4ab 100644
--- a/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc
@@ -54,7 +54,7 @@
     GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
   }
 
-  if (!HasEditableStyle(*node_))
+  if (!IsEditable(*node_))
     return;
 
   if (password_echo_enabled) {
@@ -68,7 +68,7 @@
 }
 
 void InsertIntoTextNodeCommand::DoUnapply() {
-  if (!HasEditableStyle(*node_))
+  if (!IsEditable(*node_))
     return;
 
   node_->deleteData(offset_, text_.length(), IGNORE_EXCEPTION_FOR_TESTING);
diff --git a/third_party/blink/renderer/core/editing/commands/insert_list_command.cc b/third_party/blink/renderer/core/editing/commands/insert_list_command.cc
index 461a853..f8d16f4 100644
--- a/third_party/blink/renderer/core/editing/commands/insert_list_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/insert_list_command.cc
@@ -339,17 +339,17 @@
   Node* list_child_node = EnclosingListChild(selection_node);
   bool switch_list_type = false;
   if (list_child_node) {
-    if (!HasEditableStyle(*list_child_node->parentNode()))
+    if (!IsEditable(*list_child_node->parentNode()))
       return false;
     // Remove the list child.
     HTMLElement* list_element = EnclosingList(list_child_node);
     if (list_element) {
-      if (!HasEditableStyle(*list_element)) {
+      if (!IsEditable(*list_element)) {
         // Since, |listElement| is uneditable, we can't move |listChild|
         // out from |listElement|.
         return false;
       }
-      if (!HasEditableStyle(*list_element->parentNode())) {
+      if (!IsEditable(*list_element->parentNode())) {
         // Since parent of |listElement| is uneditable, we can not remove
         // |listElement| for switching list type neither unlistify.
         return false;
@@ -364,8 +364,8 @@
         return false;
       GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
     }
-    DCHECK(HasEditableStyle(*list_element));
-    DCHECK(HasEditableStyle(*list_element->parentNode()));
+    DCHECK(IsEditable(*list_element));
+    DCHECK(IsEditable(*list_element->parentNode()));
     if (!list_element->HasTagName(list_tag)) {
       // |list_child_node| will be removed from the list and a list of type
       // |type_| will be created.
@@ -471,7 +471,7 @@
     EditingState* editing_state) {
   // Since, unlistify paragraph inserts nodes into parent and removes node
   // from parent, if parent of |listElement| should be editable.
-  DCHECK(HasEditableStyle(*list_element->parentNode()));
+  DCHECK(IsEditable(*list_element->parentNode()));
   Node* next_list_child;
   Node* previous_list_child;
   Position start;
diff --git a/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc b/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc
index 9798029a..ae4dd83 100644
--- a/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc
@@ -46,7 +46,7 @@
   DCHECK(ref_child_);
   DCHECK(ref_child_->parentNode()) << ref_child_;
 
-  DCHECK(HasEditableStyle(*ref_child_->parentNode()) ||
+  DCHECK(IsEditable(*ref_child_->parentNode()) ||
          !ref_child_->parentNode()->InActiveDocument())
       << ref_child_->parentNode();
 }
@@ -56,9 +56,9 @@
   GetDocument().UpdateStyleAndLayoutTree();
   if (!parent || (should_assume_content_is_always_editable_ ==
                       kDoNotAssumeContentIsAlwaysEditable &&
-                  !HasEditableStyle(*parent)))
+                  !IsEditable(*parent)))
     return;
-  DCHECK(HasEditableStyle(*parent)) << parent;
+  DCHECK(IsEditable(*parent)) << parent;
 
   DummyExceptionStateForTesting exception_state;
   parent->InsertBefore(insert_child_.Get(), ref_child_.Get(), exception_state);
@@ -67,7 +67,7 @@
 
 void InsertNodeBeforeCommand::DoUnapply() {
   GetDocument().UpdateStyleAndLayoutTree();
-  if (!HasEditableStyle(*insert_child_))
+  if (!IsEditable(*insert_child_))
     return;
 
   insert_child_->remove(IGNORE_EXCEPTION_FOR_TESTING);
diff --git a/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc b/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc
index f989169..08b13b3 100644
--- a/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc
@@ -42,8 +42,8 @@
 }
 
 void MergeIdenticalElementsCommand::DoApply(EditingState*) {
-  if (element1_->nextSibling() != element2_ || !HasEditableStyle(*element1_) ||
-      !HasEditableStyle(*element2_))
+  if (element1_->nextSibling() != element2_ || !IsEditable(*element1_) ||
+      !IsEditable(*element2_))
     return;
 
   at_child_ = element2_->firstChild();
@@ -66,7 +66,7 @@
   Node* at_child = at_child_.Release();
 
   ContainerNode* parent = element2_->parentNode();
-  if (!parent || !HasEditableStyle(*parent))
+  if (!parent || !IsEditable(*parent))
     return;
 
   DummyExceptionStateForTesting exception_state;
diff --git a/third_party/blink/renderer/core/editing/commands/move_commands.cc b/third_party/blink/renderer/core/editing/commands/move_commands.cc
index 1e10044..968076f 100644
--- a/third_party/blink/renderer/core/editing/commands/move_commands.cc
+++ b/third_party/blink/renderer/core/editing/commands/move_commands.cc
@@ -65,7 +65,7 @@
     return 0;
   if (!(style->OverflowY() == EOverflow::kScroll ||
         style->OverflowY() == EOverflow::kAuto ||
-        HasEditableStyle(*focused_element) || frame.IsCaretBrowsingEnabled()))
+        IsEditable(*focused_element) || frame.IsCaretBrowsingEnabled()))
     return 0;
   const ScrollableArea& scrollable_area = *frame.View()->LayoutViewport();
   const int height = std::min<int>(layout_box.ClientHeight().ToInt(),
diff --git a/third_party/blink/renderer/core/editing/commands/remove_node_command.cc b/third_party/blink/renderer/core/editing/commands/remove_node_command.cc
index 12d02dc..2ebb1298 100644
--- a/third_party/blink/renderer/core/editing/commands/remove_node_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/remove_node_command.cc
@@ -49,9 +49,9 @@
   GetDocument().UpdateStyleAndLayoutTree();
   if (!parent || (should_assume_content_is_always_editable_ ==
                       kDoNotAssumeContentIsAlwaysEditable &&
-                  !HasEditableStyle(*parent) && parent->InActiveDocument()))
+                  !IsEditable(*parent) && parent->InActiveDocument()))
     return;
-  DCHECK(HasEditableStyle(*parent) || !parent->InActiveDocument()) << parent;
+  DCHECK(IsEditable(*parent) || !parent->InActiveDocument()) << parent;
 
   parent_ = parent;
   ref_child_ = node_->nextSibling();
@@ -67,7 +67,7 @@
 void RemoveNodeCommand::DoUnapply() {
   ContainerNode* parent = parent_.Release();
   Node* ref_child = ref_child_.Release();
-  if (!parent || !HasEditableStyle(*parent))
+  if (!parent || !IsEditable(*parent))
     return;
 
   parent->InsertBefore(node_.Get(), ref_child, IGNORE_EXCEPTION_FOR_TESTING);
diff --git a/third_party/blink/renderer/core/editing/commands/remove_node_preserving_children_command.cc b/third_party/blink/renderer/core/editing/commands/remove_node_preserving_children_command.cc
index 0bd763b5..3bf8ef2 100644
--- a/third_party/blink/renderer/core/editing/commands/remove_node_preserving_children_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/remove_node_preserving_children_command.cc
@@ -43,7 +43,7 @@
 
 void RemoveNodePreservingChildrenCommand::DoApply(EditingState* editing_state) {
   ABORT_EDITING_COMMAND_IF(!node_->parentNode());
-  ABORT_EDITING_COMMAND_IF(!HasEditableStyle(*node_->parentNode()));
+  ABORT_EDITING_COMMAND_IF(!IsEditable(*node_->parentNode()));
   auto* container_node = DynamicTo<ContainerNode>(node_.Get());
   if (container_node) {
     NodeVector children;
diff --git a/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc b/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc
index 9a0f26a4..cddd972 100644
--- a/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc
@@ -190,12 +190,12 @@
       !(shadow_ancestor_element && shadow_ancestor_element->GetLayoutObject() &&
         shadow_ancestor_element->GetLayoutObject()
             ->IsTextControlIncludingNG()) &&
-      HasRichlyEditableStyle(*editable_root)) {
+      IsRichlyEditable(*editable_root)) {
     RemoveInterchangeNodes(fragment_);
     return;
   }
 
-  if (!HasRichlyEditableStyle(*editable_root)) {
+  if (!IsRichlyEditable(*editable_root)) {
     bool is_plain_text = true;
     for (Node& node : NodeTraversal::ChildrenOf(*fragment_)) {
       if (IsInterchangeHTMLBRElement(&node) && &node == fragment_->lastChild())
@@ -245,7 +245,7 @@
   // Give the root a chance to change the text.
   auto* evt = MakeGarbageCollected<BeforeTextInsertedEvent>(text);
   editable_root->DefaultEventHandler(*evt);
-  if (text != evt->GetText() || !HasRichlyEditableStyle(*editable_root)) {
+  if (text != evt->GetText() || !IsRichlyEditable(*editable_root)) {
     RestoreAndRemoveTestRenderingNodesToFragment(holder);
 
     // TODO(editing-dev): Use of UpdateStyleAndLayout
@@ -653,9 +653,8 @@
       continue;
     }
 
-    if (element->parentNode() &&
-        HasRichlyEditableStyle(*element->parentNode()) &&
-        HasRichlyEditableStyle(*element)) {
+    if (element->parentNode() && IsRichlyEditable(*element->parentNode()) &&
+        IsRichlyEditable(*element)) {
       RemoveElementAttribute(element, html_names::kContenteditableAttr);
     }
   }
@@ -762,7 +761,7 @@
     Element* ancestor,
     EditingState* editing_state) {
   DCHECK(element);
-  if (!HasEditableStyle(*ancestor->parentNode()))
+  if (!IsEditable(*ancestor->parentNode()))
     return;
 
   GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
@@ -1385,7 +1384,7 @@
   if ((IsHTMLListElement(inserted_nodes.RefNode()) ||
        (IsHTMLListElement(inserted_nodes.RefNode()->firstChild()))) &&
       block_start && block_start->GetLayoutObject()->IsListItemIncludingNG() &&
-      HasEditableStyle(*block_start->parentNode())) {
+      IsEditable(*block_start->parentNode())) {
     inserted_nodes.SetRefNode(InsertAsListItems(
         To<HTMLElement>(inserted_nodes.RefNode()), block_start, insertion_pos,
         inserted_nodes, editing_state));
diff --git a/third_party/blink/renderer/core/editing/commands/set_character_data_command.cc b/third_party/blink/renderer/core/editing/commands/set_character_data_command.cc
index f852a9e..3f881b8f 100644
--- a/third_party/blink/renderer/core/editing/commands/set_character_data_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/set_character_data_command.cc
@@ -30,7 +30,7 @@
   // TODO(editing-dev): The use of updateStyleAndLayoutTree()
   // needs to be audited.  See http://crbug.com/590369 for more details.
   GetDocument().UpdateStyleAndLayoutTree();
-  if (!HasEditableStyle(*node_))
+  if (!IsEditable(*node_))
     return;
 
   DummyExceptionStateForTesting exception_state;
@@ -58,7 +58,7 @@
   // TODO(editing-dev): The use of updateStyleAndLayoutTree()
   // needs to be audited.  See http://crbug.com/590369 for more details.
   GetDocument().UpdateStyleAndLayoutTree();
-  if (!HasEditableStyle(*node_))
+  if (!IsEditable(*node_))
     return;
 
   node_->replaceData(offset_, new_text_.length(), previous_text_for_undo_,
diff --git a/third_party/blink/renderer/core/editing/commands/split_element_command.cc b/third_party/blink/renderer/core/editing/commands/split_element_command.cc
index 1f589771..c951ad7 100644
--- a/third_party/blink/renderer/core/editing/commands/split_element_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/split_element_command.cc
@@ -53,7 +53,7 @@
   DummyExceptionStateForTesting exception_state;
 
   ContainerNode* parent = element2_->parentNode();
-  if (!parent || !HasEditableStyle(*parent))
+  if (!parent || !IsEditable(*parent))
     return;
   parent->InsertBefore(element1_.Get(), element2_.Get(), exception_state);
   if (exception_state.HadException())
@@ -74,8 +74,7 @@
 }
 
 void SplitElementCommand::DoUnapply() {
-  if (!element1_ || !HasEditableStyle(*element1_) ||
-      !HasEditableStyle(*element2_))
+  if (!element1_ || !IsEditable(*element1_) || !IsEditable(*element2_))
     return;
 
   NodeVector children;
diff --git a/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc b/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc
index 1e72fc2..8a1cdc1 100644
--- a/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc
@@ -47,7 +47,7 @@
 
 void SplitTextNodeCommand::DoApply(EditingState*) {
   ContainerNode* parent = text2_->parentNode();
-  if (!parent || !HasEditableStyle(*parent))
+  if (!parent || !IsEditable(*parent))
     return;
 
   String prefix_text =
@@ -63,7 +63,7 @@
 }
 
 void SplitTextNodeCommand::DoUnapply() {
-  if (!text1_ || !HasEditableStyle(*text1_))
+  if (!text1_ || !IsEditable(*text1_))
     return;
 
   DCHECK_EQ(text1_->GetDocument(), GetDocument());
@@ -82,7 +82,7 @@
     return;
 
   ContainerNode* parent = text2_->parentNode();
-  if (!parent || !HasEditableStyle(*parent))
+  if (!parent || !IsEditable(*parent))
     return;
 
   GetDocument().Markers().MoveMarkers(*text2_, offset_, *text1_);
diff --git a/third_party/blink/renderer/core/editing/commands/split_text_node_containing_element_command.cc b/third_party/blink/renderer/core/editing/commands/split_text_node_containing_element_command.cc
index a32e6a1..e59a7cf 100644
--- a/third_party/blink/renderer/core/editing/commands/split_text_node_containing_element_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/split_text_node_containing_element_command.cc
@@ -48,8 +48,9 @@
 
   Element* parent = text_->parentElement();
   if (!parent || !parent->parentElement() ||
-      !HasEditableStyle(*parent->parentElement()))
+      !IsEditable(*parent->parentElement())) {
     return;
+  }
 
   LayoutObject* parent_layout_object = parent->GetLayoutObject();
   if (!parent_layout_object || !parent_layout_object->IsInline()) {
diff --git a/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc b/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc
index a00416b6..6a909b9 100644
--- a/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc
@@ -57,7 +57,7 @@
 void WrapContentsInDummySpanCommand::DoUnapply() {
   DCHECK(element_);
 
-  if (!dummy_span_ || !HasEditableStyle(*element_))
+  if (!dummy_span_ || !IsEditable(*element_))
     return;
 
   NodeVector children;
@@ -72,7 +72,7 @@
 void WrapContentsInDummySpanCommand::DoReapply() {
   DCHECK(element_);
 
-  if (!dummy_span_ || !HasEditableStyle(*element_))
+  if (!dummy_span_ || !IsEditable(*element_))
     return;
 
   ExecuteApply();
diff --git a/third_party/blink/renderer/core/editing/editing_style.cc b/third_party/blink/renderer/core/editing/editing_style.cc
index 2f1d7d6..b46efee 100644
--- a/third_party/blink/renderer/core/editing/editing_style.cc
+++ b/third_party/blink/renderer/core/editing/editing_style.cc
@@ -938,7 +938,7 @@
   EditingTriState state = EditingTriState::kFalse;
   bool node_is_start = true;
   for (Node& node : NodeTraversal::StartsAt(*selection.Start().AnchorNode())) {
-    if (node.GetLayoutObject() && HasEditableStyle(node)) {
+    if (node.GetLayoutObject() && IsEditable(node)) {
       auto* node_style =
           MakeGarbageCollected<CSSComputedStyleDeclaration>(&node);
       if (node_style) {
diff --git a/third_party/blink/renderer/core/editing/editing_utilities.cc b/third_party/blink/renderer/core/editing/editing_utilities.cc
index 0498c379..04f7519 100644
--- a/third_party/blink/renderer/core/editing/editing_utilities.cc
+++ b/third_party/blink/renderer/core/editing/editing_utilities.cc
@@ -376,7 +376,7 @@
   return false;
 }
 
-bool HasEditableStyle(const Node& node) {
+bool IsEditable(const Node& node) {
   // TODO(editing-dev): We shouldn't check editable style in inactive documents.
   // We should hoist this check in the call stack, replace it by a DCHECK of
   // active document and ultimately cleanup the code paths with inactive
@@ -387,7 +387,7 @@
   return HasEditableLevel(node, kEditable);
 }
 
-bool HasRichlyEditableStyle(const Node& node) {
+bool IsRichlyEditable(const Node& node) {
   // TODO(editing-dev): We shouldn't check editable style in inactive documents.
   // We should hoist this check in the call stack, replace it by a DCHECK of
   // active document and ultimately cleanup the code paths with inactive
@@ -402,7 +402,7 @@
 // TODO(dglazkov): Remove. Consumers of this code should use
 // Node:hasEditableStyle.  http://crbug.com/612560
 bool IsEditableElement(const Node& node) {
-  if (HasEditableStyle(node))
+  if (IsEditable(node))
     return true;
 
   if (auto* text_control = ToTextControlOrNull(&node)) {
@@ -419,15 +419,15 @@
 }
 
 bool IsRootEditableElement(const Node& node) {
-  return HasEditableStyle(node) && node.IsElementNode() &&
-         (!node.parentNode() || !HasEditableStyle(*node.parentNode()) ||
+  return IsEditable(node) && node.IsElementNode() &&
+         (!node.parentNode() || !IsEditable(*node.parentNode()) ||
           !node.parentNode()->IsElementNode() ||
           &node == node.GetDocument().body());
 }
 
 Element* RootEditableElement(const Node& node) {
   const Element* result = nullptr;
-  for (const Node* n = &node; n && HasEditableStyle(*n); n = n->parentNode()) {
+  for (const Node* n = &node; n && IsEditable(*n); n = n->parentNode()) {
     if (auto* element = DynamicTo<Element>(n))
       result = element;
     if (node.GetDocument().body() == n)
@@ -449,7 +449,7 @@
 
   ContainerNode* node = highest_root->parentNode();
   while (node) {
-    if (HasEditableStyle(*node))
+    if (IsEditable(*node))
       highest_root = node;
     if (IsA<HTMLBodyElement>(*node))
       break;
@@ -482,7 +482,7 @@
 
   if (node->IsDocumentNode())
     return false;
-  return HasEditableStyle(*node);
+  return IsEditable(*node);
 }
 
 bool IsEditablePosition(const PositionInFlatTree& p) {
@@ -497,7 +497,7 @@
   if (IsDisplayInsideTable(node))
     node = node->parentNode();
 
-  return HasRichlyEditableStyle(*node);
+  return IsRichlyEditable(*node);
 }
 
 Element* RootEditableElementOf(const Position& p) {
@@ -658,7 +658,7 @@
   // position falls before highestRoot.
   if (position.CompareTo(PositionTemplate<Strategy>::FirstPositionInNode(
           highest_root)) == -1 &&
-      HasEditableStyle(highest_root))
+      IsEditable(highest_root))
     return PositionTemplate<Strategy>::FirstPositionInNode(highest_root);
 
   PositionTemplate<Strategy> editable_position = position;
@@ -1187,7 +1187,7 @@
     auto* ancestor = DynamicTo<Element>(runner);
     if (!ancestor)
       continue;
-    if (root && !HasEditableStyle(*ancestor))
+    if (root && !IsEditable(*ancestor))
       continue;
     if (ancestor->HasTagName(tag_name))
       return ancestor;
@@ -1215,7 +1215,7 @@
     // Don't return a non-editable node if the input position was editable,
     // since the callers from editing will no doubt want to perform editing
     // inside the returned node.
-    if (root && !HasEditableStyle(*n))
+    if (root && !IsEditable(*n))
       continue;
     if (node_is_of_type(n))
       return n;
@@ -1249,7 +1249,7 @@
       rule == kCannotCrossEditingBoundary ? HighestEditableRoot(p) : nullptr;
   for (Node* n = p.ComputeContainerNode(); n && n != stay_within;
        n = n->parentNode()) {
-    if (root && !HasEditableStyle(*n))
+    if (root && !IsEditable(*n))
       continue;
     if (node_is_of_type(n))
       highest = n;
@@ -1411,23 +1411,23 @@
     return position_with_affinity;
   const Position& position = position_with_affinity.GetPosition();
   const Node& node = *position.ComputeContainerNode();
-  if (HasEditableStyle(node))
+  if (IsEditable(node))
     return position_with_affinity;
   // TODO(yosin): Once we fix |MostBackwardCaretPosition()| to handle
   // positions other than |kOffsetInAnchor|, we don't need to use
   // |adjusted_position|, e.g. <outer><inner contenteditable> with position
   // before <inner> vs. outer@0[1].
   // [1] editing/selection/click-outside-editable-div.html
-  const Position& adjusted_position = HasEditableStyle(*position.AnchorNode())
+  const Position& adjusted_position = IsEditable(*position.AnchorNode())
                                           ? position.ToOffsetInAnchor()
                                           : position;
   const Position& forward =
       MostForwardCaretPosition(adjusted_position, kCanCrossEditingBoundary);
-  if (HasEditableStyle(*forward.ComputeContainerNode()))
+  if (IsEditable(*forward.ComputeContainerNode()))
     return PositionWithAffinity(forward);
   const Position& backward =
       MostBackwardCaretPosition(adjusted_position, kCanCrossEditingBoundary);
-  if (HasEditableStyle(*backward.ComputeContainerNode()))
+  if (IsEditable(*backward.ComputeContainerNode()))
     return PositionWithAffinity(backward);
   return PositionWithAffinity(adjusted_position,
                               position_with_affinity.Affinity());
@@ -1710,7 +1710,7 @@
   // TODO(editing-dev): The use of UpdateStyleAndLayout
   // needs to be audited. see http://crbug.com/590369 for more details.
   node.GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
-  if (!HasRichlyEditableStyle(node))
+  if (!IsRichlyEditable(node))
     return nullptr;
   const EphemeralRange& range =
       FirstEphemeralRangeOf(node.GetDocument()
@@ -1765,7 +1765,7 @@
 
   InputEvent* before_input_event;
 
-  if (HasRichlyEditableStyle(*target) || !data_transfer) {
+  if (IsRichlyEditable(*target) || !data_transfer) {
     before_input_event = InputEvent::CreateBeforeInput(
         input_type, data_transfer, InputTypeIsCancelable(input_type),
         InputEvent::EventIsComposing::kNotComposing,
@@ -1795,8 +1795,8 @@
   // Flat Tree:
   //   <host><div ce><span1>unedittable</span></div></host>
   // e.g. editing/shadow/breaking-editing-boundaries.html
-  return !NodeTraversal::HasChildren(node) && !HasEditableStyle(node) &&
-         node.parentNode() && HasEditableStyle(*node.parentNode());
+  return !NodeTraversal::HasChildren(node) && !IsEditable(node) &&
+         node.parentNode() && IsEditable(*node.parentNode());
 }
 
 // TODO(yosin): We should not use |IsEmptyNonEditableNodeInEditable()| in
diff --git a/third_party/blink/renderer/core/editing/editing_utilities.h b/third_party/blink/renderer/core/editing/editing_utilities.h
index 923a8c1..256161e 100644
--- a/third_party/blink/renderer/core/editing/editing_utilities.h
+++ b/third_party/blink/renderer/core/editing/editing_utilities.h
@@ -76,8 +76,9 @@
 // Returns true if element is input element or has editable style.
 CORE_EXPORT bool IsEditableElement(const Node&);
 
-CORE_EXPORT bool HasEditableStyle(const Node&);
-CORE_EXPORT bool HasRichlyEditableStyle(const Node&);
+CORE_EXPORT bool IsEditable(const Node&);
+CORE_EXPORT bool IsRichlyEditable(const Node&);
+
 CORE_EXPORT bool IsRootEditableElement(const Node&);
 CORE_EXPORT Element* RootEditableElement(const Node&);
 Element* RootEditableElementOf(const Position&);
diff --git a/third_party/blink/renderer/core/editing/frame_selection.cc b/third_party/blink/renderer/core/editing/frame_selection.cc
index 67e40a6..273035f 100644
--- a/third_party/blink/renderer/core/editing/frame_selection.cc
+++ b/third_party/blink/renderer/core/editing/frame_selection.cc
@@ -519,11 +519,11 @@
       ComputeVisibleSelectionInFlatTree().End() >= focused_position)
     return true;
 
-  bool has_editable_style = HasEditableStyle(*current);
+  bool is_editable = IsEditable(*current);
   do {
     // If the selection is within an editable sub tree and that sub tree
     // doesn't have focus, the selection doesn't have focus either.
-    if (has_editable_style && !HasEditableStyle(*current))
+    if (is_editable && !IsEditable(*current))
       return false;
 
     // Selection has focus if its sub tree has focus.
@@ -721,7 +721,7 @@
 
   // This method's purpose is it to make it easier to select iframes (in order
   // to delete them).  Don't do anything if the iframe isn't deletable.
-  if (!blink::HasEditableStyle(*owner_element_parent))
+  if (!blink::IsEditable(*owner_element_parent))
     return;
 
   // Focus on the parent frame, and then select from before this element to
@@ -1101,7 +1101,7 @@
 
   Document* document = frame_->GetDocument();
   if (!ComputeVisibleSelectionInDOMTreeDeprecated().IsNone() ||
-      !(blink::HasEditableStyle(*document)))
+      !(blink::IsEditable(*document)))
     return;
 
   Element* document_element = document->documentElement();
diff --git a/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc b/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc
index 0117af89..fd2668e 100644
--- a/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc
+++ b/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc
@@ -124,7 +124,7 @@
   if (it.AtEnd())
     return;
 
-  const bool needs_text = HasEditableStyle(*container_);
+  const bool needs_text = IsEditable(*container_);
 
   // The initial buffer size can be critical for performance:
   // https://bugs.webkit.org/show_bug.cgi?id=81192
@@ -209,7 +209,7 @@
 
 String CachedTextInputInfo::GetText() const {
   DCHECK(container_);
-  DCHECK(HasEditableStyle(*container_));
+  DCHECK(IsEditable(*container_));
   return text_;
 }
 
diff --git a/third_party/blink/renderer/core/editing/ime/input_method_controller.cc b/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
index 5fe4b4a..bc5aed88 100644
--- a/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
+++ b/third_party/blink/renderer/core/editing/ime/input_method_controller.cc
@@ -93,7 +93,7 @@
     query_attribute = true;
   } else {
     element->GetDocument().UpdateStyleAndLayoutTree();
-    if (HasEditableStyle(*element))
+    if (IsEditable(*element))
       query_attribute = true;
   }
 
@@ -116,7 +116,7 @@
     query_attribute = true;
   } else {
     element->GetDocument().UpdateStyleAndLayoutTree();
-    if (HasEditableStyle(*element))
+    if (IsEditable(*element))
       query_attribute = true;
   }
 
@@ -1814,7 +1814,7 @@
   }
 
   GetDocument().UpdateStyleAndLayoutTree();
-  if (HasEditableStyle(*element))
+  if (IsEditable(*element))
     return kWebTextInputTypeContentEditable;
 
   return kWebTextInputTypeNone;
diff --git a/third_party/blink/renderer/core/editing/selection_adjuster.cc b/third_party/blink/renderer/core/editing/selection_adjuster.cc
index e34fd8f..33a2c93b 100644
--- a/third_party/blink/renderer/core/editing/selection_adjuster.cc
+++ b/third_party/blink/renderer/core/editing/selection_adjuster.cc
@@ -608,19 +608,19 @@
   static bool IsEditingBoundary(const Node& node,
                                 const Node& previous_node,
                                 bool is_previous_node_editable) {
-    return HasEditableStyle(node) != is_previous_node_editable;
+    return IsEditable(node) != is_previous_node_editable;
   }
 
   // Returns the highest ancestor of |start| along the parent chain, so that
   // all node in between them including the ancestor have the same
-  // HasEditableStyle() bit with |start|. Note that it only consider the <body>
+  // IsEditable() bit with |start|. Note that it only consider the <body>
   // subtree.
   template <typename Strategy>
   static const Node& RootBoundaryElementOf(const Node& start) {
     if (IsA<HTMLBodyElement>(start))
       return start;
 
-    const bool is_editable = HasEditableStyle(start);
+    const bool is_editable = IsEditable(start);
     const Node* result = &start;
     for (const Node& ancestor : Strategy::AncestorsOf(start)) {
       if (IsEditingBoundary<Strategy>(ancestor, *result, is_editable))
@@ -672,7 +672,7 @@
     // extent in |base_rbe| subtree that RBE(ancestor) != |base_rbe|.
     const Node* boundary = &extent_rbe;
     const Node* previous_ancestor = &extent_rbe;
-    bool previous_editable = HasEditableStyle(extent_rbe);
+    bool previous_editable = IsEditable(extent_rbe);
     for (const Node& ancestor : Strategy::AncestorsOf(extent_rbe)) {
       if (IsEditingBoundary<Strategy>(ancestor, *previous_ancestor,
                                       previous_editable))
@@ -680,7 +680,7 @@
 
       if (ancestor == base_rbe || IsA<HTMLBodyElement>(ancestor))
         break;
-      previous_editable = HasEditableStyle(ancestor);
+      previous_editable = IsEditable(ancestor);
       previous_ancestor = &ancestor;
     }
 
@@ -701,7 +701,7 @@
   if (IsShadowHost(&node) && is_previous_node_editable &&
       previous_node.OwnerShadowHost() == &node)
     return true;
-  return HasEditableStyle(node) != is_previous_node_editable;
+  return IsEditable(node) != is_previous_node_editable;
 }
 
 SelectionInDOMTree
diff --git a/third_party/blink/renderer/core/editing/selection_controller.cc b/third_party/blink/renderer/core/editing/selection_controller.cc
index a9ad2a17..ea0cb1c 100644
--- a/third_party/blink/renderer/core/editing/selection_controller.cc
+++ b/third_party/blink/renderer/core/editing/selection_controller.cc
@@ -405,8 +405,8 @@
   }
 
   bool is_handle_visible = false;
-  const bool has_editable_style = HasEditableStyle(*inner_node);
-  if (has_editable_style) {
+  const bool is_editable = IsEditable(*inner_node);
+  if (is_editable) {
     const bool is_text_box_empty =
         !RootEditableElement(*inner_node)->HasChildren();
     const bool not_left_click =
@@ -434,7 +434,7 @@
 
   // SelectionControllerTest_SetCaretAtHitTestResultWithDisconnectedPosition
   // makes the IsValidFor() check fail.
-  if (has_editable_style && event.Event().FromTouch() &&
+  if (is_editable && event.Event().FromTouch() &&
       position_to_use.IsValidFor(*frame_->GetDocument())) {
     frame_->GetTextSuggestionController().HandlePotentialSuggestionTap(
         position_to_use.GetPosition());
@@ -646,7 +646,7 @@
     const String word = PlainText(
         range, TextIteratorBehavior::Builder()
                    .SetEmitsObjectReplacementCharacter(
-                       HasEditableStyle(*range.StartPosition().AnchorNode()))
+                       IsEditable(*range.StartPosition().AnchorNode()))
                    .Build());
     if (word.length() >= 1 && word[0] == '\n') {
       // We should not select word from end of line, e.g.
@@ -1090,7 +1090,7 @@
 
     SelectionInFlatTree::Builder builder;
     Node* node = event.InnerNode();
-    if (node && node->GetLayoutObject() && HasEditableStyle(*node)) {
+    if (node && node->GetLayoutObject() && IsEditable(*node)) {
       const PositionInFlatTreeWithAffinity pos =
           CreateVisiblePosition(
               PositionWithAffinityOfHitTestResult(event.GetHitTestResult()))
@@ -1166,7 +1166,7 @@
 
   Node* inner_node = hit_test_result.InnerPossiblyPseudoNode();
   inner_node->GetDocument().UpdateStyleAndLayoutTree();
-  bool inner_node_is_selectable = HasEditableStyle(*inner_node) ||
+  bool inner_node_is_selectable = IsEditable(*inner_node) ||
                                   inner_node->IsTextNode() ||
                                   inner_node->CanStartSelection();
   if (!inner_node_is_selectable)
diff --git a/third_party/blink/renderer/core/editing/selection_modifier_line.cc b/third_party/blink/renderer/core/editing/selection_modifier_line.cc
index 535b262..e3e9ffaf 100644
--- a/third_party/blink/renderer/core/editing/selection_modifier_line.cc
+++ b/third_party/blink/renderer/core/editing/selection_modifier_line.cc
@@ -194,7 +194,7 @@
     const LayoutObject* const layout_object =
         cursor.Current().GetLayoutObject();
     return layout_object && layout_object->GetNode() &&
-           HasEditableStyle(*layout_object->GetNode());
+           blink::IsEditable(*layout_object->GetNode());
   }
 
   static PositionInFlatTreeWithAffinity PositionForPoint(
@@ -341,10 +341,10 @@
 }
 
 Node* PreviousLeafWithSameEditability(const Node& node) {
-  const bool editable = HasEditableStyle(node);
+  const bool editable = IsEditable(node);
   for (Node* runner = PreviousAtomicLeafNode(node); runner;
        runner = PreviousAtomicLeafNode(*runner)) {
-    if (editable == HasEditableStyle(*runner))
+    if (editable == IsEditable(*runner))
       return runner;
   }
   return nullptr;
@@ -356,7 +356,7 @@
 
   for (Node* runner = NextAtomicLeafNode(*node); runner;
        runner = NextAtomicLeafNode(*runner)) {
-    if (editable == HasEditableStyle(*runner))
+    if (editable == IsEditable(*runner))
       return runner;
   }
   return nullptr;
@@ -410,7 +410,7 @@
   // TODO(xiaochengh): We probably also need to pass in the starting editability
   // to |PreviousLeafWithSameEditability|.
   const bool is_editable =
-      HasEditableStyle(*position.GetPosition().ComputeContainerNode());
+      IsEditable(*position.GetPosition().ComputeContainerNode());
   Node* next_node = NextLeafWithGivenEditability(node, is_editable);
   while (next_node && InSameLine(*next_node, position)) {
     next_node = NextLeafWithGivenEditability(next_node, is_editable);
@@ -490,7 +490,7 @@
   // Could not find a previous line. This means we must already be on the first
   // line. Move to the start of the content in this block, which effectively
   // moves us to the start of the line we're on.
-  Element* root_element = HasEditableStyle(*node)
+  Element* root_element = IsEditable(*node)
                               ? RootEditableElement(*node)
                               : node->GetDocument().documentElement();
   if (!root_element)
@@ -562,7 +562,7 @@
   // Could not find a next line. This means we must already be on the last line.
   // Move to the end of the content in this block, which effectively moves us
   // to the end of the line we're on.
-  Element* root_element = HasEditableStyle(*node)
+  Element* root_element = IsEditable(*node)
                               ? RootEditableElement(*node)
                               : node->GetDocument().documentElement();
   if (!root_element)
diff --git a/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc b/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
index f4a24d3..98847d68 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
+++ b/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
@@ -431,7 +431,7 @@
 
   for (Node& node : NodeTraversal::InclusiveDescendantsOf(element)) {
     auto* text_node = DynamicTo<Text>(node);
-    if ((elements_type == ElementsType::kAll || !HasEditableStyle(node)) &&
+    if ((elements_type == ElementsType::kAll || !IsEditable(node)) &&
         text_node) {
       GetFrame().GetDocument()->Markers().RemoveMarkersForNode(
           *text_node, DocumentMarker::MarkerTypes::Misspelling());
@@ -774,8 +774,7 @@
   }
   HTMLElement* element =
       Traversal<HTMLElement>::FirstAncestorOrSelf(*position.AnchorNode());
-  return element && element->IsSpellCheckingEnabled() &&
-         HasEditableStyle(*element);
+  return element && element->IsSpellCheckingEnabled() && IsEditable(*element);
 }
 
 STATIC_ASSERT_ENUM(kWebTextDecorationTypeSpelling, kTextDecorationTypeSpelling);
diff --git a/third_party/blink/renderer/core/editing/visible_units.cc b/third_party/blink/renderer/core/editing/visible_units.cc
index 543e056..5fdb366 100644
--- a/third_party/blink/renderer/core/editing/visible_units.cc
+++ b/third_party/blink/renderer/core/editing/visible_units.cc
@@ -115,8 +115,8 @@
   // editable body.
   Node* const node = position.ComputeContainerNode();
   if (node && node->GetDocument().documentElement() == node &&
-      !HasEditableStyle(*node) && node->GetDocument().body() &&
-      HasEditableStyle(*node->GetDocument().body()))
+      !IsEditable(*node) && node->GetDocument().body() &&
+      IsEditable(*node->GetDocument().body()))
     return next.IsNotNull() ? next : prev;
 
   Element* const editing_root = RootEditableElementOf(position);
@@ -242,7 +242,7 @@
   if (!highest_root) {
     const Node* last_non_editable = anchor.ComputeContainerNode();
     for (const Node& ancestor : Strategy::AncestorsOf(*last_non_editable)) {
-      if (HasEditableStyle(ancestor)) {
+      if (IsEditable(ancestor)) {
         return PositionWithAffinityTemplate<Strategy>(
             PositionTemplate<Strategy>::LastPositionInNode(*last_non_editable));
       }
@@ -292,8 +292,7 @@
   Node* boundary = position.ComputeContainerNode();
   while (boundary != document_element &&
          NonShadowBoundaryParentNode<Strategy>(boundary) &&
-         HasEditableStyle(*anchor_node) ==
-             HasEditableStyle(*Strategy::Parent(*boundary)))
+         IsEditable(*anchor_node) == IsEditable(*Strategy::Parent(*boundary)))
     boundary = NonShadowBoundaryParentNode<Strategy>(boundary);
 
   return boundary;
@@ -656,7 +655,7 @@
   DCHECK(adjusted_position.IsNotNull()) << position;
 #endif
   PositionIteratorAlgorithm<Strategy> last_visible(adjusted_position);
-  const bool start_editable = HasEditableStyle(*start_node);
+  const bool start_editable = IsEditable(*start_node);
   Node* last_node = start_node;
   bool boundary_crossed = false;
   absl::optional<WritingMode> writing_mode;
@@ -664,10 +663,10 @@
        !current_pos.AtStart(); current_pos.Decrement()) {
     Node* current_node = current_pos.GetNode();
     // Don't check for an editability change if we haven't moved to a different
-    // node, to avoid the expense of computing hasEditableStyle().
+    // node, to avoid the expense of computing IsEditable().
     if (current_node != last_node) {
       // Don't change editability.
-      const bool current_editable = HasEditableStyle(*current_node);
+      const bool current_editable = IsEditable(*current_node);
       if (start_editable != current_editable) {
         if (rule == kCannotCrossEditingBoundary)
           break;
@@ -806,7 +805,7 @@
                 position.AnchorNode(),
                 Strategy::CaretMaxOffset(*position.AnchorNode()))
           : position);
-  const bool start_editable = HasEditableStyle(*start_node);
+  const bool start_editable = IsEditable(*start_node);
   Node* last_node = start_node;
   bool boundary_crossed = false;
   absl::optional<WritingMode> writing_mode;
@@ -814,10 +813,10 @@
        !current_pos.AtEnd(); current_pos.Increment()) {
     Node* current_node = current_pos.GetNode();
     // Don't check for an editability change if we haven't moved to a different
-    // node, to avoid the expense of computing hasEditableStyle().
+    // node, to avoid the expense of computing IsEditable().
     if (current_node != last_node) {
       // Don't change editability.
-      const bool current_editable = HasEditableStyle(*current_node);
+      const bool current_editable = IsEditable(*current_node);
       if (start_editable != current_editable) {
         if (rule == kCannotCrossEditingBoundary)
           break;
@@ -929,19 +928,18 @@
   PositionTemplate<Strategy> next_position =
       MostForwardCaretPosition(positions, kCanCrossEditingBoundary);
   if (positions.AtFirstEditingPositionForNode() && next_position.IsNotNull() &&
-      !HasEditableStyle(*next_position.AnchorNode()))
+      !IsEditable(*next_position.AnchorNode()))
     return true;
 
   PositionTemplate<Strategy> prev_position =
       MostBackwardCaretPosition(positions, kCanCrossEditingBoundary);
   if (positions.AtLastEditingPositionForNode() && prev_position.IsNotNull() &&
-      !HasEditableStyle(*prev_position.AnchorNode()))
+      !IsEditable(*prev_position.AnchorNode()))
     return true;
 
   return next_position.IsNotNull() &&
-         !HasEditableStyle(*next_position.AnchorNode()) &&
-         prev_position.IsNotNull() &&
-         !HasEditableStyle(*prev_position.AnchorNode());
+         !IsEditable(*next_position.AnchorNode()) &&
+         prev_position.IsNotNull() && !IsEditable(*prev_position.AnchorNode());
 }
 
 template <typename Strategy>
@@ -1008,10 +1006,10 @@
         anchor_node->GetDocument().body() == anchor_node) {
       if (!HasRenderedNonAnonymousDescendantsWithHeight(layout_object))
         return position.AtFirstEditingPositionForNode();
-      return HasEditableStyle(*anchor_node) && AtEditingBoundary(position);
+      return IsEditable(*anchor_node) && AtEditingBoundary(position);
     }
   } else {
-    return HasEditableStyle(*anchor_node) && AtEditingBoundary(position);
+    return IsEditable(*anchor_node) && AtEditingBoundary(position);
   }
 
   return false;
diff --git a/third_party/blink/renderer/core/editing/visible_units_paragraph.cc b/third_party/blink/renderer/core/editing/visible_units_paragraph.cc
index 8bd8b2e1..258ea337 100644
--- a/third_party/blink/renderer/core/editing/visible_units_paragraph.cc
+++ b/third_party/blink/renderer/core/editing/visible_units_paragraph.cc
@@ -61,7 +61,7 @@
       PositionTemplate<Strategy>::FirstPositionInOrBeforeNode(*start_node),
       kCannotCrossEditingBoundary);
   ContainerNode* const highest_root = HighestEditableRoot(position);
-  const bool start_node_is_editable = HasEditableStyle(*start_node);
+  const bool start_node_is_editable = IsEditable(*start_node);
 
   Node* candidate_node = start_node;
   PositionAnchorType candidate_type = position.AnchorType();
@@ -96,12 +96,11 @@
   while (previous_node_iterator) {
     if (boundary_crossing_rule == kCannotCrossEditingBoundary &&
         !NodeIsUserSelectAll(previous_node_iterator) &&
-        HasEditableStyle(*previous_node_iterator) != start_node_is_editable)
+        IsEditable(*previous_node_iterator) != start_node_is_editable)
       break;
     if (boundary_crossing_rule == kCanSkipOverEditingBoundary) {
       while (previous_node_iterator &&
-             HasEditableStyle(*previous_node_iterator) !=
-                 start_node_is_editable) {
+             IsEditable(*previous_node_iterator) != start_node_is_editable) {
         previous_node_iterator = previousNode();
       }
       if (!previous_node_iterator ||
@@ -188,7 +187,7 @@
       PositionTemplate<Strategy>::FirstPositionInOrBeforeNode(*start_node),
       kCannotCrossEditingBoundary);
   ContainerNode* const highest_root = HighestEditableRoot(position);
-  const bool start_node_is_editable = HasEditableStyle(*start_node);
+  const bool start_node_is_editable = IsEditable(*start_node);
 
   Node* candidate_node = start_node;
   PositionAnchorType candidate_type = position.AnchorType();
@@ -211,11 +210,11 @@
   while (next_node_iterator) {
     if (boundary_crossing_rule == kCannotCrossEditingBoundary &&
         !NodeIsUserSelectAll(next_node_iterator) &&
-        HasEditableStyle(*next_node_iterator) != start_node_is_editable)
+        IsEditable(*next_node_iterator) != start_node_is_editable)
       break;
     if (boundary_crossing_rule == kCanSkipOverEditingBoundary) {
       while (next_node_iterator &&
-             HasEditableStyle(*next_node_iterator) != start_node_is_editable)
+             IsEditable(*next_node_iterator) != start_node_is_editable)
         next_node_iterator = nextNode();
       if (!next_node_iterator ||
           !next_node_iterator->IsDescendantOf(highest_root))
diff --git a/third_party/blink/renderer/core/exported/web_element.cc b/third_party/blink/renderer/core/exported/web_element.cc
index c991ed1..3fbf2ef 100644
--- a/third_party/blink/renderer/core/exported/web_element.cc
+++ b/third_party/blink/renderer/core/exported/web_element.cc
@@ -64,7 +64,7 @@
   const Element* element = ConstUnwrap<Element>();
 
   element->GetDocument().UpdateStyleAndLayoutTree();
-  if (HasEditableStyle(*element))
+  if (blink::IsEditable(*element))
     return true;
 
   if (auto* text_control = ToTextControlOrNull(element)) {
diff --git a/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc b/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc
index aeb26365..66da1f8 100644
--- a/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_input_method_controller_impl.cc
@@ -90,7 +90,7 @@
   if (range.IsNotNull()) {
     Node* node = range.StartPosition().ComputeContainerNode();
     GetFrame()->GetDocument()->UpdateStyleAndLayoutTree();
-    if (!node || !HasEditableStyle(*node))
+    if (!node || !IsEditable(*node))
       return false;
   }
 
diff --git a/third_party/blink/renderer/core/exported/web_node.cc b/third_party/blink/renderer/core/exported/web_node.cc
index c3ce76a..5d20e5da 100644
--- a/third_party/blink/renderer/core/exported/web_node.cc
+++ b/third_party/blink/renderer/core/exported/web_node.cc
@@ -146,7 +146,7 @@
 
 bool WebNode::IsContentEditable() const {
   private_->GetDocument().UpdateStyleAndLayoutTree();
-  return HasEditableStyle(*private_);
+  return blink::IsEditable(*private_);
 }
 
 bool WebNode::IsInsideFocusableElementOrARIAWidget() const {
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index 3f6460c..28725a71 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -835,7 +835,7 @@
   }
 
   // Editable nodes should not be highlighted (e.g., <input>)
-  if (HasEditableStyle(*best_touch_node))
+  if (IsEditable(*best_touch_node))
     return nullptr;
 
   Node* hand_cursor_ancestor = FindLinkHighlightAncestor(best_touch_node);
@@ -1871,7 +1871,7 @@
         focused_frame->GetDocument()->UpdateStyleAndLayoutTree();
         if (element->IsTextControl()) {
           element->UpdateSelectionOnFocus(SelectionBehaviorOnFocus::kRestore);
-        } else if (HasEditableStyle(*element)) {
+        } else if (IsEditable(*element)) {
           // updateFocusAppearance() selects all the text of
           // contentseditable DIVs. So we set the selection explicitly
           // instead. Note that this has the side effect of moving the
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
index e4a632d..86f90ef6a 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -786,9 +786,10 @@
   // processing keyboard events even though focus has been moved to the page and
   // keystrokes get eaten as a result.
   document->UpdateStyleAndLayoutTree();
-  if (HasEditableStyle(*old_focused_element) ||
-      old_focused_element->IsTextControl())
+  if (IsEditable(*old_focused_element) ||
+      old_focused_element->IsTextControl()) {
     frame_->Selection().Clear();
+  }
 }
 
 void LocalFrameMojoHandler::GetResourceSnapshotForWebBundle(
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc
index 46ed344..c65d649 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.cc
+++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -119,7 +119,7 @@
 HTMLAnchorElement::~HTMLAnchorElement() = default;
 
 bool HTMLAnchorElement::SupportsFocus() const {
-  if (HasEditableStyle(*this))
+  if (IsEditable(*this))
     return HTMLElement::SupportsFocus();
   // If not a link we should still be able to focus the element if it has
   // tabIndex.
@@ -216,7 +216,7 @@
 }
 
 void HTMLAnchorElement::SetActive(bool active) {
-  if (active && HasEditableStyle(*this))
+  if (active && IsEditable(*this))
     return;
 
   HTMLElement::SetActive(active);
@@ -288,7 +288,7 @@
 bool HTMLAnchorElement::CanStartSelection() const {
   if (!IsLink())
     return HTMLElement::CanStartSelection();
-  return HasEditableStyle(*this);
+  return IsEditable(*this);
 }
 
 bool HTMLAnchorElement::draggable() const {
@@ -358,7 +358,7 @@
 }
 
 bool HTMLAnchorElement::IsLiveLink() const {
-  return IsLink() && !HasEditableStyle(*this);
+  return IsLink() && !IsEditable(*this);
 }
 
 void HTMLAnchorElement::SendPings(const KURL& destination_url) const {
diff --git a/third_party/blink/renderer/core/html/html_body_element.cc b/third_party/blink/renderer/core/html/html_body_element.cc
index 25534fa..8f956d4 100644
--- a/third_party/blink/renderer/core/html/html_body_element.cc
+++ b/third_party/blink/renderer/core/html/html_body_element.cc
@@ -301,7 +301,7 @@
 bool HTMLBodyElement::SupportsFocus() const {
   // This override is needed because the inherited method bails if the parent is
   // editable.  The <body> should be focusable even if <html> is editable.
-  return HasEditableStyle(*this) || HTMLElement::SupportsFocus();
+  return IsEditable(*this) || HTMLElement::SupportsFocus();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc
index c2ee4bef..ccfd16d 100644
--- a/third_party/blink/renderer/core/html/html_element.cc
+++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -1773,7 +1773,7 @@
   // <textarea>) or has contentEditable attribute on, we should enter a space or
   // newline even in spatial navigation mode instead of handling it as a "click"
   // action.
-  if (IsTextControl() || HasEditableStyle(*this))
+  if (IsTextControl() || IsEditable(*this))
     return;
   int char_code = event.charCode();
   if (char_code == '\r' || char_code == ' ') {
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc
index bc64875..7f137a4e 100644
--- a/third_party/blink/renderer/core/input/event_handler.cc
+++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -441,7 +441,7 @@
 bool EventHandler::UsesHandCursor(const Node* node) {
   if (!node)
     return false;
-  return ((node->IsLink() || IsSubmitImage(node)) && !HasEditableStyle(*node));
+  return ((node->IsLink() || IsSubmitImage(node)) && !IsEditable(*node));
 }
 
 void EventHandler::CursorUpdateTimerFired(TimerBase*) {
@@ -520,7 +520,7 @@
   if (node->IsTextNode() && (node->CanStartSelection() || result.IsOverLink()))
     return true;
 
-  return HasEditableStyle(*node);
+  return IsEditable(*node);
 }
 
 absl::optional<ui::Cursor> EventHandler::SelectCursor(
diff --git a/third_party/blink/renderer/core/layout/hit_test_result.cc b/third_party/blink/renderer/core/layout/hit_test_result.cc
index 958be189..400d4795 100644
--- a/third_party/blink/renderer/core/layout/hit_test_result.cc
+++ b/third_party/blink/renderer/core/layout/hit_test_result.cc
@@ -511,7 +511,7 @@
   if (auto* input = DynamicTo<HTMLInputElement>(*inner_node_))
     return !input->IsDisabledOrReadOnly() && input->IsTextField();
 
-  return HasEditableStyle(*inner_node_);
+  return IsEditable(*inner_node_);
 }
 
 std::tuple<bool, ListBasedHitTestBehavior>
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc
index 6e52015..deb0c7ca 100644
--- a/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -1388,8 +1388,8 @@
   DCHECK(child.NonPseudoNode());
   return !ancestor || !ancestor->Parent() ||
          (ancestor->HasLayer() && IsA<LayoutView>(ancestor->Parent())) ||
-         HasEditableStyle(*ancestor->NonPseudoNode()) ==
-             HasEditableStyle(*child.NonPseudoNode());
+         IsEditable(*ancestor->NonPseudoNode()) ==
+             IsEditable(*child.NonPseudoNode());
 }
 
 // FIXME: This function should go on LayoutObject.
diff --git a/third_party/blink/renderer/core/layout/layout_box_hot.cc b/third_party/blink/renderer/core/layout/layout_box_hot.cc
index 900cba32..391d1b0e 100644
--- a/third_party/blink/renderer/core/layout/layout_box_hot.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_hot.cc
@@ -88,7 +88,7 @@
   if (ScrollsOverflow() && has_scrollable_overflow)
     return true;
 
-  return node && HasEditableStyle(*node);
+  return node && IsEditable(*node);
 }
 
 const NGLayoutResult* LayoutBox::CachedLayoutResult(
diff --git a/third_party/blink/renderer/core/layout/layout_table_cell.cc b/third_party/blink/renderer/core/layout/layout_table_cell.cc
index f7fda0ec..551b23e 100644
--- a/third_party/blink/renderer/core/layout/layout_table_cell.cc
+++ b/third_party/blink/renderer/core/layout/layout_table_cell.cc
@@ -1249,7 +1249,7 @@
 
 bool LayoutTableCell::HasLineIfEmpty() const {
   NOT_DESTROYED();
-  if (GetNode() && HasEditableStyle(*GetNode()))
+  if (GetNode() && IsEditable(*GetNode()))
     return true;
 
   return LayoutBlock::HasLineIfEmpty();
diff --git a/third_party/blink/renderer/core/layout/line/root_inline_box.cc b/third_party/blink/renderer/core/layout/line/root_inline_box.cc
index 42b0774a..365a40ca 100644
--- a/third_party/blink/renderer/core/layout/line/root_inline_box.cc
+++ b/third_party/blink/renderer/core/layout/line/root_inline_box.cc
@@ -417,7 +417,7 @@
 
 static bool IsEditableLeaf(InlineBox* leaf) {
   return leaf && leaf->GetLineLayoutItem().GetNode() &&
-         HasEditableStyle(*leaf->GetLineLayoutItem().GetNode());
+         IsEditable(*leaf->GetLineLayoutItem().GetNode());
 }
 
 const LayoutObject* RootInlineBox::ClosestLeafChildForPoint(
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
index 4d18d39..389a836 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
@@ -456,6 +456,38 @@
   EXPECT_EQ(line_index, 6u);
 }
 
+TEST_F(NGFragmentItemTest, Outline) {
+  LoadAhem();
+  SetBodyInnerHTML(R"HTML(
+    <style>
+    #target {
+      font-family: Ahem;
+      font-size: 10px;
+      width: 200px;
+    }
+    .inline-box {
+      border: 5px solid blue;
+    }
+    .inline-block {
+      display: inline-block;
+    }
+    </style>
+    <div id="target">
+      <span class="inline-box">
+        <span class="inline-block">X<span>
+      </span>
+    </div>
+  )HTML");
+  auto* target = To<LayoutBlockFlow>(GetLayoutObjectByElementId("target"));
+  Vector<PhysicalRect> rects = target->OutlineRects(
+      nullptr, PhysicalOffset(), NGOutlineType::kIncludeBlockVisualOverflow);
+  EXPECT_THAT(rects,
+              testing::ElementsAre(
+                  PhysicalRect(0, 0, 200, 10),   // <div id="target">
+                  PhysicalRect(5, 0, 10, 10),    // <span class="inline-box">
+                  PhysicalRect(5, 0, 10, 10)));  // <span class="inline-block">
+}
+
 // Various nodes/elements to test insertions.
 using CreateNode = Node* (*)(Document&);
 static CreateNode node_creators[] = {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
index 6d01cdd..c8358bc 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -1614,9 +1614,9 @@
     ancestor = ancestor->Parent();
   if (!ancestor || !ancestor->Parent() ||
       (ancestor->HasLayer() && ancestor->Parent()->IsLayoutView()) ||
-      HasEditableStyle(*ancestor->NonPseudoNode()) ==
-          HasEditableStyle(*child_node))
+      IsEditable(*ancestor->NonPseudoNode()) == IsEditable(*child_node)) {
     return child.PositionForPoint(point_in_child);
+  }
 
   // If editiability isn't the same in the ancestor and the child, then we
   // return a visible position just before or after the child, whichever side is
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
index 6303cd2..bc6442c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
@@ -834,11 +834,10 @@
           AddOutlineRectsForDescendant(
               {child_box, item.OffsetInContainerFragment()}, outline_rects,
               additional_offset, outline_type, containing_block);
-          if (child_box->IsInlineBox()) {
-            // Inline boxes have their children in the flat list. Skip them.
-            cursor->MoveToNextSkippingChildren();
-            continue;
-          }
+          // Skip descendants as they were already added.
+          DCHECK(item.IsInlineBox() || item.DescendantsCount() == 1);
+          cursor->MoveToNextSkippingChildren();
+          continue;
         }
         break;
       }
diff --git a/third_party/blink/renderer/core/layout/scroll_anchor.cc b/third_party/blink/renderer/core/layout/scroll_anchor.cc
index b07e38fa..5748f2b7 100644
--- a/third_party/blink/renderer/core/layout/scroll_anchor.cc
+++ b/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -376,7 +376,7 @@
   LayoutObject* candidate = nullptr;
   ExamineResult result{kSkip};
   auto* focused_element = document.FocusedElement();
-  if (focused_element && HasEditableStyle(*focused_element)) {
+  if (focused_element && IsEditable(*focused_element)) {
     candidate = PriorityCandidateFromNode(focused_element);
     if (candidate) {
       result = ExaminePriorityCandidate(candidate);
diff --git a/third_party/blink/renderer/core/page/drag_controller.cc b/third_party/blink/renderer/core/page/drag_controller.cc
index f8bc79e..afcd614 100644
--- a/third_party/blink/renderer/core/page/drag_controller.cc
+++ b/third_party/blink/renderer/core/page/drag_controller.cc
@@ -497,8 +497,8 @@
   Document* doc = local_root.DocumentAtPoint(
       PhysicalOffset::FromPointFRound(drag_data->ClientPosition()));
 
-  if (doc && (did_initiate_drag_ || IsA<PluginDocument>(doc) ||
-              HasEditableStyle(*doc)))
+  if (doc &&
+      (did_initiate_drag_ || IsA<PluginDocument>(doc) || IsEditable(*doc)))
     return DragOperation::kNone;
   return GetDragOperation(drag_data);
 }
@@ -753,9 +753,9 @@
     return true;
 
   if (auto* plugin = DynamicTo<HTMLPlugInElement>(result.InnerNode())) {
-    if (!plugin->CanProcessDrag() && !HasEditableStyle(*result.InnerNode()))
+    if (!plugin->CanProcessDrag() && !IsEditable(*result.InnerNode()))
       return false;
-  } else if (!HasEditableStyle(*result.InnerNode())) {
+  } else if (!IsEditable(*result.InnerNode())) {
     return false;
   }
 
@@ -836,7 +836,7 @@
 
   // Editable elements loose their draggability,
   // see https://github.com/whatwg/html/issues/3114.
-  if (HasEditableStyle(node))
+  if (IsEditable(node))
     return true;
 
   for (Node& ancestor_node : NodeTraversal::InclusiveAncestorsOf(node)) {
@@ -936,7 +936,7 @@
                                             const KURL& image_url,
                                             const String& label) {
   node->GetDocument().UpdateStyleAndLayoutTree();
-  if (HasRichlyEditableStyle(*node)) {
+  if (IsRichlyEditable(*node)) {
     // TODO(editing-dev): We should use |EphemeralRange| instead of |Range|.
     Range* range = source->GetDocument()->createRange();
     range->selectNode(node, ASSERT_NO_EXCEPTION);
diff --git a/third_party/blink/renderer/core/page/focus_controller.cc b/third_party/blink/renderer/core/page/focus_controller.cc
index 03a7e09..d3423dd 100644
--- a/third_party/blink/renderer/core/page/focus_controller.cc
+++ b/third_party/blink/renderer/core/page/focus_controller.cc
@@ -1259,7 +1259,7 @@
 }
 
 static bool RelinquishesEditingFocus(const Element& element) {
-  DCHECK(HasEditableStyle(element));
+  DCHECK(IsEditable(element));
   return element.GetDocument().GetFrame() && RootEditableElement(element);
 }
 
diff --git a/third_party/blink/renderer/core/page/spatial_navigation_controller.cc b/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
index 497e6d9..27ace35 100644
--- a/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
+++ b/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
@@ -187,7 +187,7 @@
   // suggestions.
   if (RuntimeEnabledFeatures::FocuslessSpatialNavigationEnabled()) {
     if (focused) {
-      if (HasEditableStyle(*focused) || focused->IsTextControl())
+      if (IsEditable(*focused) || focused->IsTextControl())
         return true;
     }
   }
diff --git a/third_party/blink/renderer/core/page/touch_adjustment.cc b/third_party/blink/renderer/core/page/touch_adjustment.cc
index dc0bd7c..cec737b 100644
--- a/third_party/blink/renderer/core/page/touch_adjustment.cc
+++ b/third_party/blink/renderer/core/page/touch_adjustment.cc
@@ -133,7 +133,7 @@
   if (!node->GetLayoutObject())
     return false;
   node->GetDocument().UpdateStyleAndLayoutTree();
-  if (HasEditableStyle(*node))
+  if (IsEditable(*node))
     return true;
   if (node->IsLink())
     return true;
@@ -308,13 +308,13 @@
     if (editable_ancestors.Contains(candidate))
       continue;
     candidate->GetDocument().UpdateStyleAndLayoutTree();
-    if (HasEditableStyle(*candidate)) {
+    if (IsEditable(*candidate)) {
       Node* replacement = candidate;
       Node* parent = candidate->ParentOrShadowHostNode();
 
       // Ignore parents without layout objects.  E.g. editable elements with
       // display:contents.  https://crbug.com/1196872
-      while (parent && HasEditableStyle(*parent) && parent->GetLayoutObject()) {
+      while (parent && IsEditable(*parent) && parent->GetLayoutObject()) {
         replacement = parent;
         if (editable_ancestors.Contains(replacement)) {
           replacement = nullptr;
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
index 1d209b3..4d2708d 100644
--- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
+++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -215,7 +215,7 @@
   // Clear the records queued for presentation callback to ensure no new updates
   // occur.
   records_manager_.ClearImagesQueuedForPaintTime();
-  if (frame_view_->GetFrame().IsMainFrame()) {
+  if (frame_view_->GetFrame().IsOutermostMainFrame()) {
     DCHECK(frame_view_->GetFrame().GetDocument());
     ukm::builders::Blink_PaintTiming(
         frame_view_->GetFrame().GetDocument()->UkmSourceID())
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
index 3d4ecaf..30317ce 100644
--- a/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
+++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector_test.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/paint/image_paint_timing_detector.h"
 
 #include "base/bind.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/test/trace_event_analyzer.h"
 #include "base/time/time.h"
@@ -1297,4 +1298,62 @@
   EXPECT_EQ(0u, events.size());
 }
 
+class ImagePaintTimingDetectorFencedFrameTest
+    : private ScopedFencedFramesForTest,
+      public ImagePaintTimingDetectorTest {
+ public:
+  ImagePaintTimingDetectorFencedFrameTest() : ScopedFencedFramesForTest(true) {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        features::kFencedFrames, {{"implementation_type", "mparch"}});
+  }
+
+  void InitializeFencedFrameRoot(mojom::blink::FencedFrameMode mode) {
+    web_view_helper_.InitializeWithOpener(/*opener=*/nullptr,
+                                          /*frame_client=*/nullptr,
+                                          /*view_client=*/nullptr,
+                                          /*update_settings_func=*/nullptr,
+                                          mode);
+    // Enable compositing on the page before running the document lifecycle.
+    web_view_helper_.GetWebView()
+        ->GetPage()
+        ->GetSettings()
+        .SetAcceleratedCompositingEnabled(true);
+
+    WebLocalFrameImpl& frame_impl = *web_view_helper_.LocalMainFrame();
+    frame_impl.ViewImpl()->MainFrameViewWidget()->Resize(gfx::Size(640, 480));
+
+    frame_test_helpers::LoadFrame(
+        web_view_helper_.GetWebView()->MainFrameImpl(), "about:blank");
+    GetDocument().View()->SetParentVisible(true);
+    GetDocument().View()->SetSelfVisible(true);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+INSTANTIATE_PAINT_TEST_SUITE_P(ImagePaintTimingDetectorFencedFrameTest);
+
+TEST_P(ImagePaintTimingDetectorFencedFrameTest, NotReported) {
+  ukm::TestAutoSetUkmRecorder test_ukm_recorder;
+  InitializeFencedFrameRoot(mojom::blink::FencedFrameMode::kDefault);
+  GetDocument().SetBaseURLOverride(KURL("https://test.com"));
+  SetBodyInnerHTML(R"HTML(
+      <body></body>
+    )HTML");
+
+  SetBodyInnerHTML(R"HTML(
+    <style>body {margin: 0px;}</style>
+    <img id="target"></img>
+  )HTML");
+  SetImageAndPaint("target", 3000, 3000);
+  UpdateAllLifecyclePhasesAndInvokeCallbackIfAny();
+  ImageRecord* record = LargestImage();
+  EXPECT_EQ(record, nullptr);
+  // Simulate some input event to force StopRecordEntries().
+  SimulateKeyDown();
+  auto entries = test_ukm_recorder.GetEntriesByName(UkmPaintTiming::kEntryName);
+  EXPECT_EQ(0u, entries.size());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/svg/svg_a_element.cc b/third_party/blink/renderer/core/svg/svg_a_element.cc
index 6c40962..b11b421 100644
--- a/third_party/blink/renderer/core/svg/svg_a_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_a_element.cc
@@ -171,7 +171,7 @@
 }
 
 bool SVGAElement::SupportsFocus() const {
-  if (HasEditableStyle(*this))
+  if (IsEditable(*this))
     return SVGGraphicsElement::SupportsFocus();
   // If not a link we should still be able to focus the element if it has
   // tabIndex.
@@ -206,7 +206,7 @@
 bool SVGAElement::CanStartSelection() const {
   if (!IsLink())
     return SVGElement::CanStartSelection();
-  return HasEditableStyle(*this);
+  return IsEditable(*this);
 }
 
 bool SVGAElement::WillRespondToMouseClickEvents() {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
index e9e63a0f..f8208d4 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -1269,7 +1269,7 @@
   // When a section of the document is contentEditable, all tables should be
   // treated as data tables, otherwise users may not be able to work with rich
   // text editors that allow creating and editing tables.
-  if (GetNode() && HasEditableStyle(*GetNode()))
+  if (GetNode() && blink::IsEditable(*GetNode()))
     return true;
 
   // This employs a heuristic to determine if this table should appear.
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index 94d5f8e..6be96db 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -4336,7 +4336,7 @@
       << GetDocument()->Lifecycle().ToString();
 #endif  // DCHECK_IS_ON()
 
-  if (HasEditableStyle(*node))
+  if (blink::IsEditable(*node))
     return true;
 
   // For the purposes of accessibility, atomic text fields  i.e. input and
diff --git a/third_party/blink/renderer/modules/credentialmanagement/authenticator_selection_criteria.idl b/third_party/blink/renderer/modules/credentialmanagement/authenticator_selection_criteria.idl
index 009d62fa..3dc2f9d 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/authenticator_selection_criteria.idl
+++ b/third_party/blink/renderer/modules/credentialmanagement/authenticator_selection_criteria.idl
@@ -2,15 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://w3c.github.io/webauthn/#enumdef-authenticatorattachment
-enum AuthenticatorAttachment {
-  "platform",
-  "cross-platform"
-};
-
 // https://w3c.github.io/webauthn/#dictdef-authenticatorselectioncriteria
 dictionary AuthenticatorSelectionCriteria {
-  AuthenticatorAttachment authenticatorAttachment;
+  // A DOMString expressing an AuthenticatorAttachment.
+  DOMString authenticatorAttachment;
   boolean requireResidentKey = false;
   // A DOMString expressing a ResidentKeyRequirement.
   DOMString residentKey;
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
index fad00a58..9a204cf 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
@@ -248,17 +248,16 @@
 }
 
 // static
-AuthenticatorAttachment
-TypeConverter<AuthenticatorAttachment, absl::optional<String>>::Convert(
-    const absl::optional<String>& attachment) {
+absl::optional<AuthenticatorAttachment> TypeConverter<
+    absl::optional<AuthenticatorAttachment>,
+    absl::optional<String>>::Convert(const absl::optional<String>& attachment) {
   if (!attachment.has_value())
     return AuthenticatorAttachment::NO_PREFERENCE;
   if (attachment.value() == "platform")
     return AuthenticatorAttachment::PLATFORM;
   if (attachment.value() == "cross-platform")
     return AuthenticatorAttachment::CROSS_PLATFORM;
-  NOTREACHED();
-  return AuthenticatorAttachment::NO_PREFERENCE;
+  return absl::nullopt;
 }
 
 // static
@@ -283,11 +282,18 @@
     Convert(const blink::AuthenticatorSelectionCriteria& criteria) {
   auto mojo_criteria =
       blink::mojom::blink::AuthenticatorSelectionCriteria::New();
-  absl::optional<String> attachment;
-  if (criteria.hasAuthenticatorAttachment())
-    attachment = criteria.authenticatorAttachment();
+
   mojo_criteria->authenticator_attachment =
-      ConvertTo<AuthenticatorAttachment>(attachment);
+      AuthenticatorAttachment::NO_PREFERENCE;
+  if (criteria.hasAuthenticatorAttachment()) {
+    absl::optional<String> attachment = criteria.authenticatorAttachment();
+    auto maybe_attachment =
+        ConvertTo<absl::optional<AuthenticatorAttachment>>(attachment);
+    if (maybe_attachment) {
+      mojo_criteria->authenticator_attachment = *maybe_attachment;
+    }
+  }
+
   absl::optional<ResidentKeyRequirement> resident_key;
   if (criteria.hasResidentKey()) {
     resident_key = ConvertTo<absl::optional<ResidentKeyRequirement>>(
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h
index 44d496b..03685449 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h
+++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h
@@ -97,12 +97,11 @@
       const String&);
 };
 
-// TODO(crbug.com/1092328): Second template parameter should be
-// absl::optional<blink::V8AuthenticatorAttachment>.
 template <>
-struct TypeConverter<blink::mojom::blink::AuthenticatorAttachment,
-                     absl::optional<String>> {
-  static blink::mojom::blink::AuthenticatorAttachment Convert(
+struct TypeConverter<
+    absl::optional<blink::mojom::blink::AuthenticatorAttachment>,
+    absl::optional<String>> {
+  static absl::optional<blink::mojom::blink::AuthenticatorAttachment> Convert(
       const absl::optional<String>&);
 };
 
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
index f254b216..f441b07b 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
@@ -85,6 +85,7 @@
 
 namespace {
 
+using mojom::blink::AuthenticatorAttachment;
 using mojom::blink::AuthenticatorStatus;
 using mojom::blink::CredentialInfo;
 using mojom::blink::CredentialInfoPtr;
@@ -1402,6 +1403,23 @@
   }
 
   if (options->publicKey()->hasAuthenticatorSelection() &&
+      options->publicKey()
+          ->authenticatorSelection()
+          ->hasAuthenticatorAttachment()) {
+    absl::optional<String> attachment = options->publicKey()
+                                            ->authenticatorSelection()
+                                            ->authenticatorAttachment();
+    if (!mojo::ConvertTo<absl::optional<AuthenticatorAttachment>>(attachment)) {
+      resolver->DomWindow()->AddConsoleMessage(
+          MakeGarbageCollected<ConsoleMessage>(
+              mojom::blink::ConsoleMessageSource::kJavaScript,
+              mojom::blink::ConsoleMessageLevel::kWarning,
+              "Ignoring unknown "
+              "publicKey.authenticatorSelection.authnticatorAttachment value"));
+    }
+  }
+
+  if (options->publicKey()->hasAuthenticatorSelection() &&
       !options->publicKey()->authenticatorSelection()->hasUserVerification()) {
     resolver->DomWindow()->AddConsoleMessage(
         MakeGarbageCollected<ConsoleMessage>(
diff --git a/third_party/blink/renderer/modules/presentation/presentation_request.cc b/third_party/blink/renderer/modules/presentation/presentation_request.cc
index d6d80d5d..fcb616f4 100644
--- a/third_party/blink/renderer/modules/presentation/presentation_request.cc
+++ b/third_party/blink/renderer/modules/presentation/presentation_request.cc
@@ -68,11 +68,11 @@
   Vector<KURL> parsed_urls;
   for (const auto& source : sources) {
     if (source->IsPresentationSource()) {
-      exception_state.ThrowDOMException(
-          DOMExceptionCode::kNotSupportedError,
-          "Presentation sources must be URL strings.");
+      exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+                                        "You must pass in valid URL strings.");
       return nullptr;
     }
+    DCHECK(source->IsUSVString());
     const String& url = source->GetAsUSVString();
     const KURL& parsed_url = KURL(execution_context->Url(), url);
 
diff --git a/third_party/blink/renderer/modules/presentation/presentation_request_test.cc b/third_party/blink/renderer/modules/presentation/presentation_request_test.cc
index c3d45a9e..9e72fd2 100644
--- a/third_party/blink/renderer/modules/presentation/presentation_request_test.cc
+++ b/third_party/blink/renderer/modules/presentation/presentation_request_test.cc
@@ -16,7 +16,19 @@
 namespace blink {
 namespace {
 
-HeapVector<Member<V8UnionPresentationSourceOrUSVString>> CreateSources(
+HeapVector<Member<V8UnionPresentationSourceOrUSVString>>
+CreatePresentationSources(const WTF::Vector<String>& urls) {
+  HeapVector<Member<V8UnionPresentationSourceOrUSVString>> sources;
+  for (const String& url : urls) {
+    PresentationSource* source = PresentationSource::Create();
+    source->setUrl(url);
+    sources.push_back(
+        MakeGarbageCollected<V8UnionPresentationSourceOrUSVString>(source));
+  }
+  return sources;
+}
+
+HeapVector<Member<V8UnionPresentationSourceOrUSVString>> CreateUrlSources(
     const WTF::Vector<String>& urls) {
   HeapVector<Member<V8UnionPresentationSourceOrUSVString>> sources;
   for (const String& url : urls) {
@@ -42,7 +54,7 @@
 TEST(PresentationRequestTest, TestMultipleUrlConstructor) {
   V8TestingScope scope;
   HeapVector<Member<V8UnionPresentationSourceOrUSVString>> sources =
-      CreateSources({"https://example.com", "cast://deadbeef?param=foo"});
+      CreateUrlSources({"https://example.com", "cast://deadbeef?param=foo"});
 
   PresentationRequest* request = PresentationRequest::Create(
       scope.GetExecutionContext(), sources, scope.GetExceptionState());
@@ -59,7 +71,7 @@
 TEST(PresentationRequestTest, TestMultipleUrlConstructorInvalidUrl) {
   V8TestingScope scope;
   HeapVector<Member<V8UnionPresentationSourceOrUSVString>> sources =
-      CreateSources({"https://example.com", ""});
+      CreateUrlSources({"https://example.com", ""});
 
   PresentationRequest::Create(scope.GetExecutionContext(), sources,
                               scope.GetExceptionState());
@@ -96,7 +108,7 @@
   V8TestingScope scope(KURL("https://example.test"));
 
   HeapVector<Member<V8UnionPresentationSourceOrUSVString>> sources =
-      CreateSources({"http://example.com", "https://example1.com"});
+      CreateUrlSources({"http://example.com", "https://example1.com"});
 
   PresentationRequest::Create(scope.GetExecutionContext(), sources,
                               scope.GetExceptionState());
@@ -128,8 +140,8 @@
 TEST(PresentationRequestTest, TestMultipleUrlConstructorSomeUnknownSchemes) {
   V8TestingScope scope;
   HeapVector<Member<V8UnionPresentationSourceOrUSVString>> sources =
-      CreateSources({"foobar:unknown", "https://example.com",
-                     "cast://deadbeef?param=foo", "deadbeef:random"});
+      CreateUrlSources({"foobar:unknown", "https://example.com",
+                        "cast://deadbeef?param=foo", "deadbeef:random"});
 
   PresentationRequest* request = PresentationRequest::Create(
       scope.GetExecutionContext(), sources, scope.GetExceptionState());
@@ -146,7 +158,7 @@
 TEST(PresentationRequestTest, TestMultipleUrlConstructorAllUnknownSchemes) {
   V8TestingScope scope;
   HeapVector<Member<V8UnionPresentationSourceOrUSVString>> sources =
-      CreateSources({"foobar:unknown", "deadbeef:random"});
+      CreateUrlSources({"foobar:unknown", "deadbeef:random"});
 
   PresentationRequest::Create(scope.GetExecutionContext(), sources,
                               scope.GetExceptionState());
@@ -155,5 +167,19 @@
             scope.GetExceptionState().CodeAs<DOMExceptionCode>());
 }
 
+TEST(PresentationRequestTest, TestPresentationSourceNotAllowed) {
+  V8TestingScope scope;
+  PresentationRequest::Create(
+      scope.GetExecutionContext(),
+      CreatePresentationSources({"https://example.com"}),
+      scope.GetExceptionState());
+  // Currently we do not allow the PresentationSource specialization of
+  // V8UnionPresentationSourceOrUSVString to be used to create a
+  // PresentationRequest.
+  EXPECT_TRUE(scope.GetExceptionState().HadException());
+  EXPECT_EQ(DOMExceptionCode::kNotSupportedError,
+            scope.GetExceptionState().CodeAs<DOMExceptionCode>());
+}
+
 }  // anonymous namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/presentation/presentation_source.idl b/third_party/blink/renderer/modules/presentation/presentation_source.idl
index ef57e9e6..249372a 100644
--- a/third_party/blink/renderer/modules/presentation/presentation_source.idl
+++ b/third_party/blink/renderer/modules/presentation/presentation_source.idl
@@ -8,7 +8,8 @@
 // Indicates the preferred tradeoff between low latency and smooth streaming.
 // The actual behavior is implementation specific. Only applies to mirroring
 // sources.
-[RuntimeEnabled=SiteInitiatedMirroring]
+// TODO(crbug.com/600726): Set RuntimeEnabled here if support is ever added for
+// enums (currently it is a no-op).
 enum CaptureLatency {
   "default",
   // Having a smooth stream is prioritized over having a low latency.
@@ -19,7 +20,8 @@
 
 // Indicates where the audio playback should occur. Only applies to mirroring
 // sources.
-[RuntimeEnabled=SiteInitiatedMirroring]
+// TODO(crbug.com/600726): Set RuntimeEnabled here if support is ever added for
+// enums (currently it is a no-op).
 enum AudioPlaybackDestination {
   "receiver",
   "controller",
diff --git a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
index df8e04e5..6bfa6004 100644
--- a/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
+++ b/third_party/blink/renderer/modules/scheduler/dom_scheduler.cc
@@ -161,9 +161,9 @@
   signal_to_task_queue_map_.insert(
       signal,
       MakeGarbageCollected<DOMTaskQueue>(std::move(task_queue), priority));
-  signal->AddPriorityChangeAlgorithm(WTF::Bind(&DOMScheduler::OnPriorityChange,
-                                               WrapWeakPersistent(this),
-                                               WrapWeakPersistent(signal)));
+  signal->AddPriorityChangeAlgorithm(
+      WTF::BindRepeating(&DOMScheduler::OnPriorityChange,
+                         WrapWeakPersistent(this), WrapWeakPersistent(signal)));
 }
 
 void DOMScheduler::OnPriorityChange(DOMTaskSignal* signal) {
diff --git a/third_party/blink/renderer/modules/scheduler/dom_task_signal.cc b/third_party/blink/renderer/modules/scheduler/dom_task_signal.cc
index 7a17f27d..e822128c 100644
--- a/third_party/blink/renderer/modules/scheduler/dom_task_signal.cc
+++ b/third_party/blink/renderer/modules/scheduler/dom_task_signal.cc
@@ -25,7 +25,8 @@
   return priority_;
 }
 
-void DOMTaskSignal::AddPriorityChangeAlgorithm(base::OnceClosure algorithm) {
+void DOMTaskSignal::AddPriorityChangeAlgorithm(
+    base::RepeatingClosure algorithm) {
   priority_change_algorithms_.push_back(std::move(algorithm));
 }
 
@@ -44,10 +45,9 @@
   priority_ = priority;
   priority_change_status_ = PriorityChangeStatus::kPriorityHasChanged;
 
-  for (base::OnceClosure& closure : priority_change_algorithms_) {
-    std::move(closure).Run();
+  for (base::RepeatingClosure& closure : priority_change_algorithms_) {
+    closure.Run();
   }
-  priority_change_algorithms_.clear();
 
   auto* init = TaskPriorityChangeEventInit::Create();
   init->setPreviousPriority(previous_priority);
diff --git a/third_party/blink/renderer/modules/scheduler/dom_task_signal.h b/third_party/blink/renderer/modules/scheduler/dom_task_signal.h
index f4a90ff5..c1d4746 100644
--- a/third_party/blink/renderer/modules/scheduler/dom_task_signal.h
+++ b/third_party/blink/renderer/modules/scheduler/dom_task_signal.h
@@ -36,7 +36,7 @@
   AtomicString priority();
   DEFINE_ATTRIBUTE_EVENT_LISTENER(prioritychange, kPrioritychange)
 
-  void AddPriorityChangeAlgorithm(base::OnceClosure algorithm);
+  void AddPriorityChangeAlgorithm(base::RepeatingClosure algorithm);
   void SignalPriorityChange(const AtomicString& priority, ExceptionState&);
 
   bool IsTaskSignal() const override { return true; }
@@ -53,7 +53,7 @@
   PriorityChangeStatus priority_change_status_ =
       PriorityChangeStatus::kNoPriorityChange;
 
-  Vector<base::OnceClosure> priority_change_algorithms_;
+  Vector<base::RepeatingClosure> priority_change_algorithms_;
 
   bool is_priority_changing_ = false;
 };
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
index 9fb04a7..b8987384 100644
--- a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
+++ b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
@@ -237,8 +237,6 @@
       return WGPUTextureFormat_Depth24Plus;
     case V8GPUTextureFormat::Enum::kDepth24PlusStencil8:
       return WGPUTextureFormat_Depth24PlusStencil8;
-    case V8GPUTextureFormat::Enum::kDepth24UnormStencil8:
-      return WGPUTextureFormat_Depth24UnormStencil8;
     case V8GPUTextureFormat::Enum::kDepth16Unorm:
       return WGPUTextureFormat_Depth16Unorm;
     case V8GPUTextureFormat::Enum::kStencil8:
@@ -449,8 +447,6 @@
       return WGPUFeatureName_DawnShaderFloat16;
     case V8GPUFeatureName::Enum::kDepthClamping:
       return WGPUFeatureName_DepthClamping;
-    case V8GPUFeatureName::Enum::kDepth24UnormStencil8:
-      return WGPUFeatureName_Depth24UnormStencil8;
     case V8GPUFeatureName::Enum::kDepth32FloatStencil8:
       return WGPUFeatureName_Depth32FloatStencil8;
     case V8GPUFeatureName::Enum::kIndirectFirstInstance:
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
index b50cf1a..d0eda40 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
@@ -38,9 +38,6 @@
 
   for (WGPUFeatureName f : feature_names) {
     switch (f) {
-      case WGPUFeatureName_Depth24UnormStencil8:
-        features->AddFeatureName("depth24unorm-stencil8");
-        break;
       case WGPUFeatureName_Depth32FloatStencil8:
         features->AddFeatureName("depth32float-stencil8");
         break;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl b/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl
index a6125b1..90ec6fe8e 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl
@@ -12,7 +12,6 @@
     "timestamp-query",
     "shader-float16",
     "depth-clamping",
-    "depth24unorm-stencil8",
     "depth32float-stencil8",
     "indirect-first-instance",
     "chromium-experimental-dp4a",
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl
index a1998aa..0f96f006 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_texture_descriptor.idl
@@ -68,7 +68,6 @@
     "depth32float-stencil8",
     "depth24plus",
     "depth24plus-stencil8",
-    "depth24unorm-stencil8",
     "depth16unorm",
     "stencil8",
     /* Block Compression (BC) formats */
@@ -125,5 +124,5 @@
     "astc-12x10-unorm",
     "astc-12x10-unorm-srgb",
     "astc-12x12-unorm",
-    "astc-12x12-unorm-srgb"
+    "astc-12x12-unorm-srgb",
 };
diff --git a/third_party/blink/renderer/modules/webgpu/texture_utils.cc b/third_party/blink/renderer/modules/webgpu/texture_utils.cc
index 96e7a1e..8e2387c 100644
--- a/third_party/blink/renderer/modules/webgpu/texture_utils.cc
+++ b/third_party/blink/renderer/modules/webgpu/texture_utils.cc
@@ -168,7 +168,6 @@
 
     case WGPUTextureAspect_StencilOnly:
       switch (format) {
-        case WGPUTextureFormat_Depth24UnormStencil8:
         case WGPUTextureFormat_Depth24PlusStencil8:
         case WGPUTextureFormat_Depth32FloatStencil8:
           return {1u, 1u, 1u};
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
index c8f24b7..184ce12 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -482,7 +482,7 @@
 
   HeapMojoRemote<mojom::blink::BlobRegistry> blob_registry_remote_;
 
-  // Lazily initialized when the first <link rel=webbundle> is inserted.
+  // Lazily initialized when the first <script type=webbundle> is inserted.
   Member<SubresourceWebBundleList> subresource_web_bundles_;
 
   // This is not in the bit field below because we want to use AutoReset.
diff --git a/third_party/blink/tools/check_testharness_expected_pass.py b/third_party/blink/tools/check_testharness_expected_pass.py
index e426e88..fc64df7 100755
--- a/third_party/blink/tools/check_testharness_expected_pass.py
+++ b/third_party/blink/tools/check_testharness_expected_pass.py
@@ -16,7 +16,13 @@
 
 paths = []
 
-for path in sys.argv[1:]:
+if len(sys.argv) == 3 and sys.argv[1] == '--path-files':
+    with open(sys.argv[2]) as f:
+        filelist = [x.strip() for x in f.readlines()]
+else:
+    filelist = sys.argv[1:]
+
+for path in filelist:
     # Call .decode() with errors="ignore" because there are a few files that
     # are invalid UTF-8 and will otherwise trigger decode exceptions.
     content = open(path, 'rb').read().decode(errors="ignore")
diff --git a/third_party/blink/web_tests/PRESUBMIT.py b/third_party/blink/web_tests/PRESUBMIT.py
index 757e52a..f07a96a 100644
--- a/third_party/blink/web_tests/PRESUBMIT.py
+++ b/third_party/blink/web_tests/PRESUBMIT.py
@@ -12,6 +12,7 @@
 import inspect
 import os
 import sys
+import tempfile
 
 USE_PYTHON3 = True
 
@@ -32,31 +33,29 @@
         '..', 'tools', 'check_testharness_expected_pass.py')
 
     # When running git cl presubmit --all this presubmit may be asked to check
-    # ~19,000 files, leading to a command line that is over 2,000,000 characters.
-    # This goes past the Windows 8191 character cmd.exe limit and causes cryptic
-    # failures. To avoid these we break the command up into smaller pieces. The
-    # non-Windows limit is chosen so that the code that splits up commands will
-    # get some exercise on other platforms.
-    # Depending on how long the command is on Windows the error may be:
-    #     The command line is too long.
-    # Or it may be:
-    #     OSError: Execution failed with error: [WinError 206] The filename or
-    #     extension is too long.
-    # I suspect that the latter error comes from CreateProcess hitting its 32768
-    # character limit.
-    files_per_command = 25 if input_api.is_windows else 1000
-    results = []
-    for i in range(0, len(baseline_files), files_per_command):
-        args = [input_api.python3_executable, checker_path]
-        args.extend(baseline_files[i:i + files_per_command])
-        _, errs = input_api.subprocess.Popen(
-            args,
-            stdout=input_api.subprocess.PIPE,
-            stderr=input_api.subprocess.PIPE,
-            universal_newlines=True).communicate()
-        if errs:
-            results.append(output_api.PresubmitError(errs))
-    return results
+    # ~19,000 files. Passing these on the command line would far exceed Windows
+    # limits, so we use --path-files instead.
+
+    # We have to set delete=False and then let the object go out of scope so
+    # that the file can be opened by name on Windows.
+    with tempfile.NamedTemporaryFile('w+', newline='', delete=False) as f:
+        for path in baseline_files:
+            f.write('%s\n' % path)
+        paths_name = f.name
+
+    args = [
+        input_api.python3_executable, checker_path, '--path-files', paths_name
+    ]
+    _, errs = input_api.subprocess.Popen(
+        args,
+        stdout=input_api.subprocess.PIPE,
+        stderr=input_api.subprocess.PIPE,
+        universal_newlines=True).communicate()
+
+    os.remove(paths_name)
+    if errs:
+        return [output_api.PresubmitError(errs)]
+    return []
 
 
 def _TestharnessGenericBaselinesToCheck(input_api):
diff --git a/third_party/blink/web_tests/external/wpt/scheduler/task-controller-setPriority-repeated.any.js b/third_party/blink/web_tests/external/wpt/scheduler/task-controller-setPriority-repeated.any.js
new file mode 100644
index 0000000..fae3ec6c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/scheduler/task-controller-setPriority-repeated.any.js
@@ -0,0 +1,60 @@
+// META: title=Scheduler: TaskController.setPriority() repeated calls
+// META: global=window,worker
+'use strict';
+
+promise_test(async t => {
+  const controller = new TaskController();
+  const signal = controller.signal;
+
+  const tasks = [];
+  const runOrder = [];
+  const callback = id => { runOrder.push(id); };
+
+  tasks.push(scheduler.postTask(() => callback(0), {signal}));
+  tasks.push(scheduler.postTask(() => callback(1), {priority: 'user-blocking'}));
+  tasks.push(scheduler.postTask(() => callback(2), {priority: 'user-visible' }));
+
+  controller.setPriority('background');
+  assert_equals(signal.priority, 'background');
+
+  await Promise.all(tasks);
+  assert_equals(runOrder.toString(), '1,2,0');
+
+  while (tasks.length) { tasks.pop(); }
+  while (runOrder.length) { runOrder.pop(); }
+
+  tasks.push(scheduler.postTask(() => callback(3), {signal}));
+  tasks.push(scheduler.postTask(() => callback(4), {priority: 'user-blocking'}));
+  tasks.push(scheduler.postTask(() => callback(5), {priority: 'user-visible' }));
+
+  controller.setPriority('user-blocking');
+  assert_equals(signal.priority, 'user-blocking');
+
+  await Promise.all(tasks);
+  assert_equals(runOrder.toString(), '3,4,5');
+}, 'TaskController.setPriority() changes the priority of all associated tasks when called repeatedly');
+
+promise_test(async t => {
+  const controller = new TaskController();
+  const signal = controller.signal;
+
+  const tasks = [];
+  const runOrder = [];
+  const callback = id => { runOrder.push(id); };
+
+  tasks.push(scheduler.postTask(() => callback(0), {signal}));
+  tasks.push(scheduler.postTask(() => callback(1), {priority: 'user-blocking'}));
+  tasks.push(scheduler.postTask(() => callback(2), {priority: 'user-visible' }));
+
+  controller.setPriority('background');
+  assert_equals(signal.priority, 'background');
+
+  controller.setPriority('user-visible');
+  assert_equals(signal.priority, 'user-visible');
+
+  controller.setPriority('user-blocking');
+  assert_equals(signal.priority, 'user-blocking');
+
+  await Promise.all(tasks);
+  assert_equals(runOrder.toString(), '0,1,2');
+}, 'TaskController.setPriority() changes the priority of all associated tasks when called repeatedly before tasks run');
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/resources/test-helpers.js b/third_party/blink/web_tests/external/wpt/web-bundle/resources/test-helpers.js
index b89b7efb..5c380c8 100644
--- a/third_party/blink/web_tests/external/wpt/web-bundle/resources/test-helpers.js
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/resources/test-helpers.js
@@ -54,48 +54,6 @@
          (lower_crossorigin  === 'use-credentials');
 }
 
-function addLinkAndWaitForLoad(url, resources, crossorigin) {
-  return new Promise((resolve, reject) => {
-    if (!isValidCrossOriginAttribute(crossorigin)) {
-      reject('invalid crossorigin attribute: ' + crossorigin);
-      return;
-    }
-    const link = document.createElement("link");
-    link.rel = "webbundle";
-    link.href = url;
-    if (crossorigin) {
-      link.crossOrigin = crossorigin;
-    }
-    for (const resource of resources) {
-      link.resources.add(resource);
-    }
-    link.onload = () => resolve(link);
-    link.onerror = () => reject(link);
-    document.body.appendChild(link);
-  });
-}
-
-function addLinkAndWaitForError(url, resources, crossorigin) {
-  return new Promise((resolve, reject) => {
-    if (!isValidCrossOriginAttribute(crossorigin)) {
-      reject('invalid crossorigin attribute: ' + crossorigin);
-      return;
-    }
-    const link = document.createElement("link");
-    link.rel = "webbundle";
-    link.href = url;
-    if (crossorigin) {
-      link.crossOrigin = crossorigin;
-    }
-    for (const resource of resources) {
-      link.resources.add(resource);
-    }
-    link.onload = () => reject(link);
-    link.onerror = () => resolve(link);
-    document.body.appendChild(link);
-  });
-}
-
 function addScriptAndWaitForError(url) {
   return new Promise((resolve, reject) => {
     const script = document.createElement("script");
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-request-destination.https.tentative.sub.html b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-request-destination.https.tentative.sub.html
index 92662c6..da12f3d 100644
--- a/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-request-destination.https.tentative.sub.html
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/subresource-loading/script-request-destination.https.tentative.sub.html
@@ -19,7 +19,7 @@
     // bundle only if a 'Sec-Fetch-Dest: webbundle' header is present in a request.
     // Otherwise, returns an empty body with 400 status code.
     //
-    // In this wpt, we assume that a <link> element fires a load event correctly if
+    // In this wpt, we assume that a <script> element fires a load event correctly if
     // a valid format webbundle is returned.
 
     const same_origin_bundle =
@@ -33,7 +33,8 @@
         await addElementAndWaitForLoad(element);
         element.remove();
       }
-    }, '"Sec-Fetch-Dest: webbundle" header must be present in a request for a bundle' + " with the <link>-based API.");
+    }, '"Sec-Fetch-Dest: webbundle" header must be present in a request for a bundle'
+     + " with <script type=webbundle>.");
 
     promise_test(async () => {
       const res = await fetch(same_origin_bundle);
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-authnrselection.https.html b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-authnrselection.https.html
index e263532..85b0f90 100644
--- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-authnrselection.https.html
+++ b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-authnrselection.https.html
@@ -22,12 +22,6 @@
     // attachment
     var authnrSelAttachPlatform = cloneObject(defaultAuthnrSel);
     authnrSelAttachPlatform.authenticatorAttachment = "platform";
-    var authnrSelBadAttachEmptyStr = cloneObject(defaultAuthnrSel);
-    authnrSelBadAttachEmptyStr.authenticatorAttachment = "";
-    var authnrSelBadAttachEmptyObj = cloneObject(defaultAuthnrSel);
-    authnrSelBadAttachEmptyObj.authenticatorAttachment = {};
-    var authnrSelBadAttachNull = cloneObject(defaultAuthnrSel);
-    authnrSelBadAttachNull.authenticatorAttachment = null;
     // resident key
     var authnrSelRkTrue = cloneObject(defaultAuthnrSel);
     authnrSelRkTrue.requireResidentKey = true;
@@ -42,9 +36,6 @@
     new CreateCredentialsTest("options.publicKey.authenticatorSelection", "none").runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection is string", TypeError);
 
     // authenticatorSelection bad attachment values
-    new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelBadAttachEmptyStr).runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection attachment is empty string", TypeError);
-    new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelBadAttachEmptyObj).runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection attachment is empty object", TypeError);
-    new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelBadAttachNull).runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection attachment is null", TypeError);
     // the physically plugged-in or virtual authenticator should be a cross-platform authenticator.
     new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelAttachPlatform)
       .modify("options.publicKey.timeout", 300)
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-passing.https.html b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-passing.https.html
index ae515a5..2d8fb14 100644
--- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-passing.https.html
+++ b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-passing.https.html
@@ -72,6 +72,14 @@
     // attachment
     var authnrSelAttachUndef = cloneObject(defaultAuthnrSel);
     authnrSelAttachUndef.authenticatorAttachment = undefined;
+    var authnrSelAttachEmptyStr = cloneObject(defaultAuthnrSel);
+    authnrSelAttachEmptyStr.authenticatorAttachment = "";
+    var authnrSelAttachEmptyObj = cloneObject(defaultAuthnrSel);
+    authnrSelAttachEmptyObj.authenticatorAttachment = {};
+    var authnrSelAttachNull = cloneObject(defaultAuthnrSel);
+    authnrSelAttachNull.authenticatorAttachment = null;
+    var authnrSelAttachUnknownValue = cloneObject(defaultAuthnrSel);
+    authnrSelAttachUnknownValue.authenticatorAttachment = "unknown-value";
     // resident key
     var authnrSelRkUndef = cloneObject(defaultAuthnrSel);
     authnrSelRkUndef.requireResidentKey = undefined;
@@ -97,6 +105,10 @@
 
     // authnr selection attachment
     new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelAttachUndef).runTest("authenticatorSelection attachment undefined");
+    new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelAttachEmptyStr).runTest("authenticatorSelection attachment empty string");
+    new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelAttachEmptyObj).runTest("authenticatorSelection attachment empty object");
+    new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelAttachNull).runTest("authenticatorSelection attachment null");
+    new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelAttachUnknownValue).runTest("authenticatorSelection attachment unknown value");
 
     // authnr selection resident key
     new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelRkUndef).runTest("authenticatorSelection residentKey undefined");
diff --git a/third_party/blink/web_tests/platform/linux/css3/filters/effect-all-on-background-hw-expected.png b/third_party/blink/web_tests/platform/linux/css3/filters/effect-all-on-background-hw-expected.png
new file mode 100644
index 0000000..15df417
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/css3/filters/effect-all-on-background-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/filters/effect-reference-composite-hw-expected.png b/third_party/blink/web_tests/platform/linux/css3/filters/effect-reference-composite-hw-expected.png
new file mode 100644
index 0000000..ff5d1f3
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/css3/filters/effect-reference-composite-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/inspector-protocol/emulation/set-vision-deficiency-expected.txt b/third_party/blink/web_tests/platform/linux/inspector-protocol/emulation/set-vision-deficiency-expected.txt
new file mode 100644
index 0000000..1622e25e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/inspector-protocol/emulation/set-vision-deficiency-expected.txt
@@ -0,0 +1,54 @@
+Tests that vision deficiencies can be emulated.
+<p>Emulating "none":
+<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFRJREFUWIXt18ENACAMw8DA5N0chnCQePgGiKz+ujI5aZru3K6uPWAgZSBlIGUgZSBlIGUgZSBlILWS030iyr6/oIGUgZSBlIGUgZSBlIGUgZSB1AXNwwVLtuf+dAAAAABJRU5ErkJggg==">
+<p>Emulating "achromatopsia":
+<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFdJREFUWIXt18ENACAMw0BArNuVuwoM4SDx8A0QWf11VtUZQd2dnBsruvaAgZSBlIGUgZSBlIGUgZSBlIHUTv8Qad9f0EDKQMpAykDKQMpAykDKQMpA6gKkyAfMkeetfgAAAABJRU5ErkJggg==">
+<p>Emulating "blurredVision":
+<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAj1JREFUWIXtlt1O20AQhb/9iRMTQwBFkKfoS/e5eonEFQIlsWOz3unFbCCtCriskbjwkUaKlM3o02R3zjH8+Clc3MHiAYoaTAArgPC+liBzYAXhBvpbOGxgt4btCpoSHj1gYW8+6PW2PBd3cPULqnsoduA6MKL1riqQBcgGQgOdUSi3hHgGcQ6lwOHTbAmwfIDzezi/g8UT2A5M5OMJViArPRdm0F2BqyG0cOhhH+HzgzsBnNUw28H8CRaPCmiHAPZ6RCp4roEDFB34HnyEIh3LhPTYAL7Tv9Z24NqBgAVIqxUD+AAugpMEJSNN0EReyqYyccAdjCARRPRRGdLdzYf6E/BF8lpmyCuWfxR/fc6XHa3TF2kCzNUEmKsJMFcne7ACetSjhjhJmc66L0JTebgG1iAh7dhWHWKQ1S1AZlpYkp0wpp14ZAVxo5YlZQId4gYuwZ3r72IB0UE83ppxID39DfQN9HPod2r8gwKrBXFACeEa+qX2OEKGsQDDLbQG2ivgAC6kp/MRoAExIAWEJbRr6CroFtB5xpvgYaNJ2NbwnLKgHWj20QAOwhyeK9hfaq/WQ7DQ5EN6dmuN6aHVsOmGxP2jjP6d0enkmhL2Z3AoYOf0+20epGe7As40pvshOfANyN5D7RWu9jq9TLgEWEI3hyLq3fP/CXh8DMFCl6qxvK6dPBmWQShPknBOzybtwO14u9BA1JFVmT23Jy1HlElb+dvq24eFCTBXE2CuJsBcTYC5mgBzNQHm6tsD/ganw+eIciY5ZgAAAABJRU5ErkJggg==">
+<p>Emulating "none":
+<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFRJREFUWIXt18ENACAMw8DA5N0chnCQePgGiKz+ujI5aZru3K6uPWAgZSBlIGUgZSBlIGUgZSBlILWS030iyr6/oIGUgZSBlIGUgZSBlIGUgZSB1AXNwwVLtuf+dAAAAABJRU5ErkJggg==">
+<p>Emulating "deuteranopia":
+<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAGNJREFUWIXt10ENgDAQBdFtReAGQzVQDdWHBlRwABHzSXqYJ+BnsrdtcxxvBa3rTs5Vj679wEDKQMpAykDKQMpAykDKQMpAqtX5RH+StO0vaCBlIGUgZSBlIGUgZSBlIGUg9QEgIQa9hKQMdAAAAABJRU5ErkJggg==">
+<p>Emulating "none":
+<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFRJREFUWIXt18ENACAMw8DA5N0chnCQePgGiKz+ujI5aZru3K6uPWAgZSBlIGUgZSBlIGUgZSBlILWS030iyr6/oIGUgZSBlIGUgZSBlIGUgZSB1AXNwwVLtuf+dAAAAABJRU5ErkJggg==">
+<p>Emulating "protanopia":
+<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFxJREFUWIXt17ENACEMBEFDldRB/hG90gYUsYf0wU4Bp5UztzXrVNC3o3PVo2sPGEgZSBlIGUgZSBlIGUgZSBlItRon+0SE/f6CBlIGUgZSBlIGUgZSBlIGUgZSF6dNBvu7bH4DAAAAAElFTkSuQmCC">
+<p>Emulating "tritanopia":
+<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFlJREFUWIXt10ENACAQxEAgqEEbEhCNAxDRJeHREbBp7ne1rHlK0h7RuRZde8BAykDKQMpAykDKQMpAykDKQKqnf4i07y9oIGUgZSBlIGUgZSBlIGUgZSB1AS8fBG2mWYWcAAAAAElFTkSuQmCC">
+<p>Emulating "tritanopia":
+<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFlJREFUWIXt10ENACAQxEAgqEEbEhCNAxDRJeHREbBp7ne1rHlK0h7RuRZde8BAykDKQMpAykDKQMpAykDKQKqnf4i07y9oIGUgZSBlIGUgZSBlIGUgZSB1AS8fBG2mWYWcAAAAAElFTkSuQmCC">
+<p>Emulating "some-invalid-deficiency":
+{
+  "code": -32602,
+  "message": "Unknown vision deficiency type"
+}
+<p>Emulating "":
+{
+  "code": -32602,
+  "message": "Unknown vision deficiency type"
+}
+<p>Emulating "achromatomaly":
+{
+  "code": -32602,
+  "message": "Unknown vision deficiency type"
+}
+<p>Emulating "deuteranomaly":
+{
+  "code": -32602,
+  "message": "Unknown vision deficiency type"
+}
+<p>Emulating "protanomaly":
+{
+  "code": -32602,
+  "message": "Unknown vision deficiency type"
+}
+<p>Emulating "tritanomaly":
+{
+  "code": -32602,
+  "message": "Unknown vision deficiency type"
+}
+<p>Navigating&mldr;
+<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFlJREFUWIXt10ENACAQxEAgqEEbEhCNAxDRJeHREbBp7ne1rHlK0h7RuRZde8BAykDKQMpAykDKQMpAykDKQKqnf4i07y9oIGUgZSBlIGUgZSBlIGUgZSB1AS8fBG2mWYWcAAAAAElFTkSuQmCC">
+<p>Emulating "achromatopsia":
+<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFdJREFUWIXt18ENACAMw0BArNuVuwoM4SDx8A0QWf11VtUZQd2dnBsruvaAgZSBlIGUgZSBlIGUgZSBlIHUTv8Qad9f0EDKQMpAykDKQMpAykDKQMpA6gKkyAfMkeetfgAAAABJRU5ErkJggg==">
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/oopr-canvas2d/fast/canvas/canvas-imageSmoothing-disabled-scaling-down-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/oopr-canvas2d/fast/canvas/canvas-imageSmoothing-disabled-scaling-down-expected.txt
new file mode 100644
index 0000000..8a4e4d1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/oopr-canvas2d/fast/canvas/canvas-imageSmoothing-disabled-scaling-down-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL Test drawImage with imageSmoothingEnabled=false and scaling down the source. assert_array_equals: drawImage() should have the same results with imageSmoothingEnabled = true and false when scaling down. expected property 3 to be 128 but got 127 (expected array object "255,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" got object "255,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/oopr-canvas2d/fast/canvas/canvas-large-dimensions-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/oopr-canvas2d/fast/canvas/canvas-large-dimensions-expected.txt
new file mode 100644
index 0000000..11a01e1
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/oopr-canvas2d/fast/canvas/canvas-large-dimensions-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+PASS Test Width = 1000
+PASS Test Height = 1000
+FAIL Test Width = 10000 assert_equals: expected 255 but got 0
+FAIL Test Height = 10000 assert_equals: expected 255 but got 0
+PASS Test Width = 32000
+PASS Test Height = 32000
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/css3/filters/effect-all-on-background-hw-expected.png b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/css3/filters/effect-all-on-background-hw-expected.png
new file mode 100644
index 0000000..3a54a74
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/css3/filters/effect-all-on-background-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/css3/filters/effect-reference-colorspace-hw-expected.png b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/css3/filters/effect-reference-colorspace-hw-expected.png
index 59f8d865..ddecfb7 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/css3/filters/effect-reference-colorspace-hw-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/css3/filters/effect-reference-colorspace-hw-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/css3/filters/effect-reference-composite-hw-expected.png b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/css3/filters/effect-reference-composite-hw-expected.png
index b6d5c363..f68b802 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/css3/filters/effect-reference-composite-hw-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/css3/filters/effect-reference-composite-hw-expected.png
Binary files differ
diff --git a/third_party/robolectric/3pp/fetch.py b/third_party/robolectric/3pp/fetch.py
index 3f547eb81..eb203ce 100755
--- a/third_party/robolectric/3pp/fetch.py
+++ b/third_party/robolectric/3pp/fetch.py
@@ -9,6 +9,7 @@
 
 _PATCH = 'cr2'
 _LATEST_VERSION = '12-robolectric-7732740.' + _PATCH
+# All instrumented jars + latest non-instrumented one.
 _ROBO_URL_FILES = {
     'android-all-instrumented-12-robolectric-7732740-i3.jar':
         'https://repo1.maven.org/maven2/org/robolectric/android-all-instrumented/12-robolectric-7732740-i3/android-all-instrumented-12-robolectric-7732740-i3.jar',
@@ -32,24 +33,6 @@
         'https://repo1.maven.org/maven2/org/robolectric/android-all-instrumented/4.4_r1-robolectric-r2-i3/android-all-instrumented-4.4_r1-robolectric-r2-i3.jar',
     'android-all-12-robolectric-7732740.jar':
         'https://repo1.maven.org/maven2/org/robolectric/android-all/12-robolectric-7732740/android-all-12-robolectric-7732740.jar',
-    'android-all-11-robolectric-6757853.jar':
-        'https://repo.maven.apache.org/maven2/org/robolectric/android-all/11-robolectric-6757853/android-all-11-robolectric-6757853.jar',
-    'android-all-10-robolectric-5803371.jar':
-        'https://repo1.maven.org/maven2/org/robolectric/android-all/10-robolectric-5803371/android-all-10-robolectric-5803371.jar',
-    'android-all-9-robolectric-4913185-2.jar':
-        'https://repo1.maven.org/maven2/org/robolectric/android-all/9-robolectric-4913185-2/android-all-9-robolectric-4913185-2.jar',
-    'android-all-8.1.0-robolectric-4611349.jar':
-        'https://repo1.maven.org/maven2/org/robolectric/android-all/8.1.0-robolectric-4611349/android-all-8.1.0-robolectric-4611349.jar',
-    'android-all-8.0.0_r4-robolectric-r1.jar':
-        'https://repo1.maven.org/maven2/org/robolectric/android-all/8.0.0_r4-robolectric-r1/android-all-8.0.0_r4-robolectric-r1.jar',
-    'android-all-7.1.0_r7-robolectric-r1.jar':
-        'https://repo1.maven.org/maven2/org/robolectric/android-all/7.1.0_r7-robolectric-r1/android-all-7.1.0_r7-robolectric-r1.jar',
-    'android-all-6.0.1_r3-robolectric-r1.jar':
-        'https://repo1.maven.org/maven2/org/robolectric/android-all/6.0.1_r3-robolectric-r1/android-all-6.0.1_r3-robolectric-r1.jar',
-    'android-all-5.0.2_r3-robolectric-r0.jar':
-        'https://repo1.maven.org/maven2/org/robolectric/android-all/5.0.2_r3-robolectric-r0/android-all-5.0.2_r3-robolectric-r0.jar',
-    'android-all-4.4_r1-robolectric-r2.jar':
-        'https://repo1.maven.org/maven2/org/robolectric/android-all/4.4_r1-robolectric-r2/android-all-4.4_r1-robolectric-r2.jar',
 }
 
 def do_latest():
diff --git a/third_party/robolectric/BUILD.gn b/third_party/robolectric/BUILD.gn
index 1d5f625..5b3b91c 100644
--- a/third_party/robolectric/BUILD.gn
+++ b/third_party/robolectric/BUILD.gn
@@ -16,11 +16,13 @@
     "//third_party/robolectric/lib/android-all-instrumented-9-robolectric-4913185-2-i3.jar",
     "//third_party/robolectric/lib/android-all-instrumented-10-robolectric-5803371-i3.jar",
     "//third_party/robolectric/lib/android-all-instrumented-11-robolectric-6757853-i3.jar",
+    "//third_party/robolectric/lib/android-all-instrumented-12-robolectric-7732740-i3.jar",
   ]
 }
 
-java_prebuilt("android-all-10-robolectric-5803371_java") {
-  enable_bytecode_checks = false
-  testonly = true
-  jar_path = "lib/android-all-10-robolectric-5803371.jar"
+# Robolectric tests compile against the robolectric sdk. This should be kept in
+# sync with the latest version in //third_party/android_sdk.
+android_system_java_prebuilt("robolectric_test_sdk_java") {
+  jar_path =
+      "//third_party/robolectric/lib/android-all-12-robolectric-7732740.jar"
 }
diff --git a/third_party/wpt_tools/README.chromium b/third_party/wpt_tools/README.chromium
index 06ce5a8..b280f71 100644
--- a/third_party/wpt_tools/README.chromium
+++ b/third_party/wpt_tools/README.chromium
@@ -1,7 +1,7 @@
 Name: web-platform-tests - Test Suites for Web Platform specifications
 Short Name: wpt
 URL: https://github.com/web-platform-tests/wpt/
-Version: aa27d567c10dcdb2aea6884d5155dfaaa177a800
+Version: f6e61a6aafdc22d149cd38edb6c7be67b4037716
 License: LICENSES FOR W3C TEST SUITES (https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html)
 License File: NOT_SHIPPED
 Security Critical: no
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py
index c2c5270..b560e8f 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/testrunner.py
@@ -261,7 +261,7 @@
     def __init__(self, suite_name, index, test_type, test_queue, test_source_cls, browser_cls,
                  browser_kwargs, executor_cls, executor_kwargs, stop_flag, rerun=1,
                  pause_after_test=False, pause_on_unexpected=False, restart_on_unexpected=True,
-                 debug_info=None, capture_stdio=True, recording=None):
+                 debug_info=None, capture_stdio=True, restart_on_new_group=True, recording=None):
         """Thread that owns a single TestRunner process and any processes required
         by the TestRunner (e.g. the Firefox binary).
 
@@ -332,6 +332,7 @@
         self.browser = None
 
         self.capture_stdio = capture_stdio
+        self.restart_on_new_group = restart_on_new_group
 
     def run(self):
         """Main loop for the TestRunnerManager.
@@ -722,10 +723,10 @@
             test, test_group, group_metadata = self.get_next_test()
             if test is None:
                 return RunnerManagerState.stop(force_stop)
-            if test_group is not self.state.test_group:
-                # We are starting a new group of tests, so force a restart
+            restart = (self.restart_on_new_group and
+                       test_group is not self.state.test_group)
+            if restart:
                 self.logger.info("Restarting browser for new test group")
-                restart = True
         else:
             test_group = self.state.test_group
             group_metadata = self.state.group_metadata
@@ -863,6 +864,7 @@
                  restart_on_unexpected=True,
                  debug_info=None,
                  capture_stdio=True,
+                 restart_on_new_group=True,
                  recording=None):
         self.suite_name = suite_name
         self.size = size
@@ -878,6 +880,7 @@
         self.debug_info = debug_info
         self.rerun = rerun
         self.capture_stdio = capture_stdio
+        self.restart_on_new_group = restart_on_new_group
         self.recording = recording
         assert recording is not None
 
@@ -920,6 +923,7 @@
                                         self.restart_on_unexpected,
                                         self.debug_info,
                                         self.capture_stdio,
+                                        self.restart_on_new_group,
                                         recording=self.recording)
             manager.start()
             self.pool.add(manager)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptcommandline.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptcommandline.py
index dda1fea..dab42db 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptcommandline.py
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptcommandline.py
@@ -75,6 +75,10 @@
                         default=True,
                         dest="fail_on_unexpected_pass",
                         help="Exit with status code 0 when all unexpected results are PASS")
+    parser.add_argument("--no-restart-on-new-group", action="store_false",
+                        default=True,
+                        dest="restart_on_new_group",
+                        help="Don't restart test runner when start a new test group")
 
     mode_group = parser.add_argument_group("Mode")
     mode_group.add_argument("--list-test-groups", action="store_true",
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py
index e3b7c9f..6a661db 100644
--- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py
+++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/wptrunner.py
@@ -230,6 +230,7 @@
                           run_test_kwargs["restart_on_unexpected"],
                           run_test_kwargs["debug_info"],
                           not run_test_kwargs["no_capture_stdio"],
+                          run_test_kwargs["restart_on_new_group"],
                           recording=recording) as manager_group:
             try:
                 manager_group.run(test_type, run_tests)
diff --git a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/utils.py b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/utils.py
index ef8786a7..a592e416 100644
--- a/third_party/wpt_tools/wpt/tools/wptserve/wptserve/utils.py
+++ b/third_party/wpt_tools/wpt/tools/wptserve/wptserve/utils.py
@@ -179,5 +179,17 @@
             'OpenSSL (found: %s)' % ssl.OPENSSL_VERSION)
         return True
 
+    # Note that OpenSSL's versioning scheme differs between 1.1.1 and
+    # earlier and 3.0.0. ssl.OPENSSL_VERSION_INFO returns a
+    #     (major, minor, 0, patch, 0)
+    # tuple with OpenSSL 3.0.0 and later, and a
+    #     (major, minor, fix, patch, status)
+    # tuple for older releases.
+    # Semantically, "patch" in 3.0.0+ is similar to "fix" in previous versions.
+    #
+    # What we do in the check below is allow OpenSSL 3.x.y+, 1.1.x+ and 1.0.2+.
     ssl_v = ssl.OPENSSL_VERSION_INFO
-    return ssl_v[0] == 1 and (ssl_v[1] == 1 or (ssl_v[1] == 0 and ssl_v[2] >= 2))
+    return (ssl_v[0] > 1 or
+            (ssl_v[0] == 1 and
+             (ssl_v[1] == 1 or
+              (ssl_v[1] == 0 and ssl_v[2] >= 2))))
diff --git a/tools/find_runtime_symbols/PRESUBMIT.py b/tools/find_runtime_symbols/PRESUBMIT.py
index 6f2a68c..5eb30724 100644
--- a/tools/find_runtime_symbols/PRESUBMIT.py
+++ b/tools/find_runtime_symbols/PRESUBMIT.py
@@ -8,12 +8,12 @@
 for more details on the presubmit API built into depot_tools.
 """
 
+import sys
 
 USE_PYTHON3 = True
 
 
 def CommonChecks(input_api, output_api):
-  import sys
   def join(*args):
     return input_api.os_path.join(input_api.PresubmitLocalPath(), *args)
 
@@ -23,7 +23,8 @@
     sys.path = [
       join('..', 'find_runtime_symbols'),
     ] + sys.path
-    output.extend(input_api.canned_checks.RunPylint(input_api, output_api))
+    output.extend(
+        input_api.canned_checks.RunPylint(input_api, output_api, version='2.7'))
   finally:
     sys.path = sys_path_backup
 
@@ -33,6 +34,7 @@
           output_api,
           input_api.os_path.join(input_api.PresubmitLocalPath(), 'tests'),
           files_to_check=[r'.+_test\.py$'],
+          run_on_python2=False,
           skip_shebang_check=True))
   return output
 
diff --git a/tools/find_runtime_symbols/find_runtime_symbols.py b/tools/find_runtime_symbols/find_runtime_symbols.py
index 51d129ec7..943486cc 100755
--- a/tools/find_runtime_symbols/find_runtime_symbols.py
+++ b/tools/find_runtime_symbols/find_runtime_symbols.py
@@ -42,7 +42,7 @@
 _FILES_FILENAME = 'files.json'
 
 
-class RuntimeSymbolsInProcess(object):
+class RuntimeSymbolsInProcess:
   def __init__(self):
     self.maps = None
     self._static_symbols_in_filse = {}
@@ -54,8 +54,7 @@
         if static_symbols:
           return static_symbols.find_procedure_by_runtime_address(
               runtime_address, vma)
-        else:
-          return None
+        return None
     return None
 
   def find_sourcefile(self, runtime_address):
@@ -65,8 +64,7 @@
         if static_symbols:
           return static_symbols.find_sourcefile_by_runtime_address(
               runtime_address, vma)
-        else:
-          return None
+        return None
     return None
 
   def find_typeinfo(self, runtime_address):
@@ -76,8 +74,7 @@
         if static_symbols:
           return static_symbols.find_typeinfo_by_runtime_address(
               runtime_address, vma)
-        else:
-          return None
+        return None
     return None
 
   @staticmethod
diff --git a/tools/find_runtime_symbols/prepare_symbol_info.py b/tools/find_runtime_symbols/prepare_symbol_info.py
index befe314..38e6e4a7 100755
--- a/tools/find_runtime_symbols/prepare_symbol_info.py
+++ b/tools/find_runtime_symbols/prepare_symbol_info.py
@@ -119,14 +119,13 @@
       if os.path.exists(os.path.join(output_dir_path, 'files.json')):
         LOGGER.warn('Using the existing directory "%s".' % output_dir_path)
         return output_dir_path, used_tempdir
+      if use_tempdir:
+        output_dir_path = tempfile.mkdtemp()
+        used_tempdir = True
+        LOGGER.warn('Using a temporary directory "%s".' % output_dir_path)
       else:
-        if use_tempdir:
-          output_dir_path = tempfile.mkdtemp()
-          used_tempdir = True
-          LOGGER.warn('Using a temporary directory "%s".' % output_dir_path)
-        else:
-          LOGGER.warn('The directory "%s" is not available.' % output_dir_path)
-          return None, used_tempdir
+        LOGGER.warn('The directory "%s" is not available.' % output_dir_path)
+        return None, used_tempdir
   else:
     LOGGER.info('Creating a new directory "%s".' % output_dir_path)
     try:
@@ -238,7 +237,7 @@
   if len(args) < 2:
     option_parser.error('Argument error.')
     return 1
-  elif len(args) == 2:
+  if len(args) == 2:
     result, _ = prepare_symbol_info(args[1],
                                     alternative_dirs=alternative_dirs_dict)
   else:
diff --git a/tools/find_runtime_symbols/reduce_debugline.py b/tools/find_runtime_symbols/reduce_debugline.py
index 6e67294..33f7da5 100755
--- a/tools/find_runtime_symbols/reduce_debugline.py
+++ b/tools/find_runtime_symbols/reduce_debugline.py
@@ -64,6 +64,7 @@
       print('%016x %s' % (address, filename))
     else:
       print('%08x %s' % (address, filename))
+  return 0
 
 
 if __name__ == '__main__':
diff --git a/tools/find_runtime_symbols/static_symbols.py b/tools/find_runtime_symbols/static_symbols.py
index cd57bac..6377363 100644
--- a/tools/find_runtime_symbols/static_symbols.py
+++ b/tools/find_runtime_symbols/static_symbols.py
@@ -20,7 +20,7 @@
     return repr(self.args[0])
 
 
-class AddressMapping(object):
+class AddressMapping:
   def __init__(self):
     self._symbol_map = {}
 
@@ -33,7 +33,7 @@
 
 class RangeAddressMapping(AddressMapping):
   def __init__(self):
-    super(RangeAddressMapping, self).__init__()
+    super().__init__()
     self._sorted_start_list = []
     self._is_sorted = True
 
@@ -57,7 +57,7 @@
     return self._symbol_map[found_start_address]
 
 
-class Procedure(object):
+class Procedure:
   """A class for a procedure symbol and an address range for the symbol."""
 
   def __init__(self, start, end, name):
@@ -77,7 +77,7 @@
     return '%x-%x: %s' % (self.start, self.end, self.name)
 
 
-class ElfSection(object):
+class ElfSection:
   """A class for an elf section header."""
 
   def __init__(
@@ -114,7 +114,7 @@
     return '%x+%x(%x) %s' % (self.address, self.size, self.offset, self.name)
 
 
-class StaticSymbolsInFile(object):
+class StaticSymbolsInFile:
   """Represents static symbol information in a binary file."""
 
   def __init__(self, my_name):
@@ -169,7 +169,7 @@
         found_header = True
         break
     if not found_header:
-      return None
+      return
 
     for line in f:
       line = line.rstrip()
@@ -201,7 +201,7 @@
   def _parse_nm_bsd_line(line):
     if line[8] == ' ':
       return line[0:8], line[9], line[11:]
-    elif line[16] == ' ':
+    if line[16] == ' ':
       return line[0:16], line[17], line[19:]
     raise ParsingException('Invalid nm output.')
 
@@ -249,11 +249,11 @@
       # that is, a line with type 'T'.  If we never see a 'T' entry,
       # we'll just go ahead and process the first entry (which never
       # got touched in the queue), and ignore the others.
-      if start_val == last_start and (sym_type == 't' or sym_type == 'T'):
+      if start_val == last_start and sym_type in ('t', 'T'):
         # We are the 'T' symbol at this address, replace previous symbol.
         routine = sym_name
         continue
-      elif start_val == last_start:
+      if start_val == last_start:
         # We're not the 'T' symbol at this address, so ignore us.
         continue
 
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 9ecd07f..722bff3 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -7675,6 +7675,15 @@
   </description>
 </action>
 
+<action name="DownloadNotification.Button_Review">
+  <owner>xinghuilu@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
+  <description>
+    User pushes &quot;Review&quot; button on download notification to trigger
+    the enterprise download review dialog.
+  </description>
+</action>
+
 <action name="DownloadNotification.Button_ShowInFolder">
   <owner>yoshiki@chromium.org</owner>
   <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 0ad193a..0de2fc7 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -10564,6 +10564,7 @@
   <int value="16" label="EMF_INVALID_EXTENSION_ID_FOR_CONTENT_SCRIPT"/>
   <int value="17" label="EMF_INVALID_EXTENSION_ID_FOR_WORKER_CONTEXT"/>
   <int value="18" label="EMF_INVALID_PORT_CONTEXT"/>
+  <int value="19" label="AWCI_INVALID_CALL_FROM_NOT_PRIMARY_MAIN_FRAME"/>
 </enum>
 
 <enum name="BadMessageReasonGuestView">
@@ -24125,6 +24126,12 @@
   <int value="3" label="Encryption unavailable"/>
 </enum>
 
+<enum name="DeleteStaleCookiesResult">
+  <int value="0" label="Old directory was not found"/>
+  <int value="1" label="Deleted succsessfully"/>
+  <int value="2" label="Error when deleting"/>
+</enum>
+
 <enum name="DemoModeApp">
   <summary>
     Pre-installed app or other window type available in Chrome OS Demo Mode.
@@ -27916,6 +27923,8 @@
   <int value="31" label="Deep scan clicked"/>
   <int value="32" label="Bypass deep scanning enabled"/>
   <int value="33" label="Bypass deep scanning clicked"/>
+  <int value="34" label="Review enabled"/>
+  <int value="35" label="Review clicked"/>
 </enum>
 
 <enum name="DownloadSource">
@@ -47273,6 +47282,14 @@
   <int value="2" label="Bulk"/>
 </enum>
 
+<enum name="HistoryClusterKeywordType">
+  <int value="0" label="Unknown"/>
+  <int value="1" label="EntityCategory"/>
+  <int value="2" label="EntityAlias"/>
+  <int value="3" label="Entity"/>
+  <int value="4" label="SearchTerms"/>
+</enum>
+
 <enum name="HistoryClustersFinalState">
   <obsolete>
     Removed as of 05/2022.
@@ -55371,6 +55388,8 @@
   <int value="-1740519217" label="disable-software-rasterizer"/>
   <int value="-1740093155" label="UnifiedMediaView:disabled"/>
   <int value="-1738416948" label="OptimizationHints:enabled"/>
+  <int value="-1738273185"
+      label="AutofillEnableGetDetailsForEnrollParsingInUploadCardResponse:disabled"/>
   <int value="-1738015645" label="ForceAppLanguagePrompt:disabled"/>
   <int value="-1737769448" label="WebUITabStripTabDragIntegration:disabled"/>
   <int value="-1736075054" label="EnableFullscreenAppList:enabled"/>
@@ -56239,6 +56258,8 @@
   <int value="-1201741587" label="DataReductionProxyDecidesTransform:disabled"/>
   <int value="-1201183153" label="enable-centered-app-list"/>
   <int value="-1199738132" label="MediaAppMultiWindow:disabled"/>
+  <int value="-1199416041"
+      label="AutofillEnableGetDetailsForEnrollParsingInUploadCardResponse:enabled"/>
   <int value="-1199159971"
       label="ContextualSuggestionsIPHReverseScroll:enabled"/>
   <int value="-1198304634"
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml
index 0fa9a69..1c1abda 100644
--- a/tools/metrics/histograms/metadata/ash/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -584,6 +584,7 @@
     <variant name="MoveSplitItemsToOriginalDirMoveExtensionsFailed"/>
     <variant name="MoveSplitItemsToOriginalDirMoveIndexedDBFailed"/>
     <variant name="MoveSplitItemsToOriginalDirMoveSplitItemsFailed"/>
+    <variant name="MoveSplitItemsToOriginalDirMoveStorageFailed"/>
     <variant name="MoveTmpDirToLacrosDirMoveFailed"/>
     <variant name="PreMigrationCleanUpDeleteLacrosDirFailed"/>
     <variant name="PreMigrationCleanUpDeleteTmpDirFailed"/>
@@ -591,6 +592,7 @@
     <variant name="PreMigrationCleanUpNotEnoughSpace"/>
     <variant name="SetupAshDirCopyExtensionsFailed"/>
     <variant name="SetupAshDirCopyIndexedDBFailed"/>
+    <variant name="SetupAshDirCopyStorageFailed"/>
     <variant name="SetupAshDirCreateDirFailed"/>
     <variant name="SetupAshDirCreateSplitDirFailed"/>
     <variant name="SetupAshDirMigrateLevelDBForLocalStateFailed"/>
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml
index c086797..58b7a6e 100644
--- a/tools/metrics/histograms/metadata/network/histograms.xml
+++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -2804,6 +2804,17 @@
   </summary>
 </histogram>
 
+<histogram name="NetworkService.ClearStaleDataDirectoryResult"
+    enum="DeleteStaleCookiesResult" expires_after="M105">
+  <owner>wfh@chromium.org</owner>
+  <owner>pasko@chromium.org</owner>
+  <summary>
+    The result of an attempt to delete stale network context data directory
+    (e.g. cookies). Recorded during construction of network context for Chrome
+    and Safebrowsing. Android only.
+  </summary>
+</histogram>
+
 <histogram name="NetworkService.ConcerningRequestHeader.AddedOnRedirect"
     enum="ConcerningHeaderPresent" expires_after="2019-11-01">
   <owner>mmenke@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/omnibox/histograms.xml b/tools/metrics/histograms/metadata/omnibox/histograms.xml
index edbbc29..65db6ff0 100644
--- a/tools/metrics/histograms/metadata/omnibox/histograms.xml
+++ b/tools/metrics/histograms/metadata/omnibox/histograms.xml
@@ -900,18 +900,51 @@
   </summary>
 </histogram>
 
+<histogram name="Omnibox.ResumeJourneyShown.ClusterKeywordScore" units="count"
+    expires_after="2022-12-10">
+  <owner>junzou@chromium.org</owner>
+  <owner>chrome-intelligence-core@google.com</owner>
+  <summary>
+    Emits the score of matched cluster keyword of any &quot;Resume Journey&quot;
+    omnibox actions shown in the popup.
+
+    Note that these are emitted when the user uses the omnibox to go somewhere.
+    When that happens, one keyword type is emitted per action visible in the
+    popup. These are NOT emitted per-keystroke, in order to make this a suitable
+    denominator for Omnibox.SuggestionUsed.ResumeJourney.ClusterKeywordScore.
+  </summary>
+</histogram>
+
+<histogram name="Omnibox.ResumeJourneyShown.ClusterKeywordType"
+    enum="HistoryClusterKeywordType" expires_after="2022-12-10">
+  <owner>junzou@chromium.org</owner>
+  <owner>chrome-intelligence-core@google.com</owner>
+  <summary>
+    Emits the type of the matched cluster keyword of any &quot;Resume
+    Journey&quot; omnibox actions shown in the popup. The types indicate the
+    sources from which the keywords are generated in the history clustering
+    backend.
+
+    Note that these are emitted when the user uses the omnibox to go somewhere.
+    When that happens, one keyword type is emitted per action visible in the
+    popup. These are NOT emitted per-keystroke, in order to make this a suitable
+    denominator for Omnibox.SuggestionUsed.ResumeJourney.ClusterKeywordType.
+  </summary>
+</histogram>
+
 <histogram name="Omnibox.ResumeJourneyShown.PageEntityCollection"
     enum="OptimizationGuidePageEntityCollection" expires_after="2022-12-08">
   <owner>junzou@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
     Emits the top entity collection of any &quot;Resume Journey&quot; omnibox
-    actions shown in the popup.
+    actions shown in the popup. The collections are high-level verticals the
+    keywords belong to.
 
     Note that these are emitted when the user uses the omnibox to go somewhere.
     When that happens, one collection is emitted per action visible in the
     popup. These are NOT emitted per-keystroke, in order to make this a suitable
-    denominator for Omnibox.SuggestionUsed.ResumeJourney.Collection.
+    denominator for Omnibox.SuggestionUsed.ResumeJourney.PageEntityCollection.
   </summary>
 </histogram>
 
@@ -1363,6 +1396,79 @@
   </summary>
 </histogram>
 
+<histogram name="Omnibox.SuggestionUsed.ResumeJourney.ClusterKeywordScore"
+    units="count" expires_after="2022-12-10">
+  <owner>junzou@chromium.org</owner>
+  <owner>chrome-intelligence-core@google.com</owner>
+  <summary>
+    Logs the score of the matched cluster keyword of &quot;Resume Journey&quot;
+    omnibox actions actually selected by the user.
+
+    This can be combined with Omnibox.ResumeJourneyShown.ClusterKeywordScore to
+    compute the precision (or CTR) of the &quot;Resume Journey&quot; omnibox
+    action on a keyword score bucket.
+
+    It's safe to compare the total count of this metric to the total count of
+    Omnibox.ResumeJourneyShown.ClusterKeywordScore because within a single
+    popup, only zero or one &quot;Resume Journey&quot; can be shown. If multiple
+    actions start being shown in the popup, comparing to the total count becomes
+    misleading to interpret as a CTR.
+  </summary>
+</histogram>
+
+<histogram name="Omnibox.SuggestionUsed.ResumeJourney.ClusterKeywordType"
+    enum="HistoryClusterKeywordType" expires_after="2022-12-10">
+  <owner>junzou@chromium.org</owner>
+  <owner>chrome-intelligence-core@google.com</owner>
+  <summary>
+    Logs the type of the matched cluster keyword of &quot;Resume Journey&quot;
+    omnibox actions actually selected by the user.
+
+    This can be combined with Omnibox.ResumeJourneyShown.ClusterKeywordType to
+    compute the precision (or CTR) of the &quot;Resume Journey&quot; omnibox
+    action on a keyword type basis.
+
+    It's safe to compare the total count of this metric to the total count of
+    Omnibox.ResumeJourneyShown.ClusterKeywordType because within a single popup,
+    only zero or one &quot;Resume Journey&quot; can be shown. If multiple
+    actions start being shown in the popup, comparing to the total count becomes
+    misleading to interpret as a CTR.
+  </summary>
+</histogram>
+
+<histogram
+    name="Omnibox.SuggestionUsed.ResumeJourney.ClusterKeywordType.{ClusterKeywordTypeLabel}.CTR"
+    enum="BooleanSelected" expires_after="2022-12-10">
+  <owner>junzou@chromium.org</owner>
+  <owner>chrome-intelligence-core@google.com</owner>
+  <summary>
+    Emitted when the user uses the omnibox to go somewhere AND the &quot;Resume
+    Journey&quot; chip triggered by {ClusterKeywordTypeLabel} was offered in any
+    position.
+
+    This metric records &quot;Selected&quot; if the offered action chip was
+    selected, and records &quot;Not Selected&quot; if the offered action chip
+    was not selected.
+
+    Therefore the &quot;Selected&quot; bucket proportion is the CTR of the
+    action chip. Higher is better. The count of this bucket matches the
+    {ClusterKeywordTypeLabel} bucket of
+    Omnibox.SuggestionUsed.ResumeJourney.ClusterKeywordType.
+
+    The total count of both buckets is how many times we've offered the chip
+    triggered by {ClusterKeywordTypeLabel} in total, and matches the
+    {ClusterKeywordTypeLabel} bucket of
+    Omnibox.ResumeJourneyShown.ClusterKeywordType.
+  </summary>
+  <token key="ClusterKeywordTypeLabel">
+    <variant name="Entity"/>
+    <variant name="EntityAlias"/>
+    <variant name="EntityCategory"/>
+    <variant name="SearchTerms"/>
+    <variant name="Unknown"/>
+  </token>
+</histogram>
+
 <histogram name="Omnibox.SuggestionUsed.ResumeJourney.PageEntityCollection"
     enum="OptimizationGuidePageEntityCollection" expires_after="2022-12-08">
   <owner>junzou@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/sb_client/histograms.xml b/tools/metrics/histograms/metadata/sb_client/histograms.xml
index 82353ac..00f6c0d 100644
--- a/tools/metrics/histograms/metadata/sb_client/histograms.xml
+++ b/tools/metrics/histograms/metadata/sb_client/histograms.xml
@@ -254,6 +254,9 @@
 
 <histogram name="SBClientDownload.ExtractDocumentFeaturesTimeMedium" units="ms"
     expires_after="2022-10-16">
+  <obsolete>
+    Replaced with SBClientDownload.FileAnalysisDuration.Document in 06-2022.
+  </obsolete>
   <owner>drubery@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -262,6 +265,26 @@
   </summary>
 </histogram>
 
+<histogram name="SBClientDownload.FileAnalysisDuration{Analysis}" units="ms"
+    expires_after="2023-06-08">
+  <owner>drubery@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
+  <summary>
+    Records the time it takes for the SafeBrowsing download service to check the
+    safety of the contents of a download which underwent analysis for
+    {Analysis}. This only includes file feature extraction. Also see
+    SBClientDownload.DownloadRequestDuration.
+  </summary>
+  <token key="Analysis">
+    <variant name="" summary="any file type, aggregated"/>
+    <variant name=".Dmg"/>
+    <variant name=".Document" summary="Office documents"/>
+    <variant name=".Executable" summary="executables"/>
+    <variant name=".Rar"/>
+    <variant name=".Zip"/>
+  </token>
+</histogram>
+
 <histogram name="SBClientDownload.MalwareDeepScanResult.{trigger}"
     enum="SBClientDownloadCheckResult" expires_after="2023-04-28">
   <owner>drubery@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
index 9ef50c53..04f043b2 100644
--- a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
@@ -124,6 +124,20 @@
 </histogram>
 
 <histogram
+    name="SegmentationPlatform.Init.ModelUpdatedTimeDifferenceInDays.{SegmentID}"
+    units="days" expires_after="M107">
+  <owner>haileywang@chromium.org</owner>
+  <owner>chrome-segmentation-platform@google.com</owner>
+  <summary>
+    Time difference in days between when a new version of the model from
+    optimization guide is available and when the model is initialized in the
+    client for a given {SegmentID}. Recorded at startup for each model to
+    identify low values for new users. It can also be recorded during the
+    session when new version of the model was updated.
+  </summary>
+</histogram>
+
+<histogram
     name="SegmentationPlatform.Init.ProcessCreationToServiceCreationLatency"
     units="ms" expires_after="M104">
   <owner>ssid@chromium.org</owner>
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py
index a771755f..a2cbde0 100644
--- a/tools/perf/core/bot_platforms.py
+++ b/tools/perf/core/bot_platforms.py
@@ -483,7 +483,6 @@
     _GetBenchmarkConfig('system_health.memory_desktop'),
     _GetBenchmarkConfig('rendering.mobile'),
     _GetBenchmarkConfig('media.mobile'),
-    _GetBenchmarkConfig('jetstream2'),
     _GetBenchmarkConfig('speedometer2'),
     _GetBenchmarkConfig('speedometer')
 ])
@@ -491,7 +490,6 @@
     _GetBenchmarkConfig('system_health.memory_desktop'),
     _GetBenchmarkConfig('rendering.mobile'),
     _GetBenchmarkConfig('media.mobile'),
-    _GetBenchmarkConfig('jetstream2'),
     _GetBenchmarkConfig('speedometer2'),
     _GetBenchmarkConfig('speedometer')
 ])
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index dc38bde..0aae95e8 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "win": {
-            "hash": "db4447cef48723bf6a8dd9efb506493073534226",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/4b6bd99fd77249235611bdf019131f3629d40801/trace_processor_shell.exe"
+            "hash": "3df88cdecaaaad7bc0b58d8f90a813352b11f024",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/ede491751b586f41084b2cfbb9bece345206cb77/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893",
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "mac": {
-            "hash": "26d1b3878e60161947bc369b9943dff7e78c6d1a",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/87a14e27dfd58c167b0cfe269706a410d547eeee/trace_processor_shell"
+            "hash": "65bc04438e1fb682690df5932651441dccb60ad2",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/ede491751b586f41084b2cfbb9bece345206cb77/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "e1ad4861384b06d911a65f035317914b8cc975c6",
             "full_remote_path": "perfetto-luci-artifacts/v25.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "0657fa1d9d6077b30d5adc1a363c69ec16ad8e70",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/cf78152e523d9e19614030351d0adc0d5c52ba11/trace_processor_shell"
+            "hash": "d9d4b43a64ed378a237b72ad67c86913f0bce7c7",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/5fb67c4d2c82a17bf682d715662b4ab3e37116c9/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/perf/core/shard_maps/fuchsia-perf-fyi_map.json b/tools/perf/core/shard_maps/fuchsia-perf-fyi_map.json
index 04d9f8f..2e3a4fd91 100644
--- a/tools/perf/core/shard_maps/fuchsia-perf-fyi_map.json
+++ b/tools/perf/core/shard_maps/fuchsia-perf-fyi_map.json
@@ -1,14 +1,11 @@
 {
     "0": {
         "benchmarks": {
-            "jetstream2": {
-                "abridged": false
-            },
             "media.mobile": {
                 "abridged": false
             },
             "rendering.mobile": {
-                "end": 17,
+                "end": 19,
                 "abridged": false
             }
         },
@@ -28,8 +25,8 @@
     "1": {
         "benchmarks": {
             "rendering.mobile": {
-                "begin": 17,
-                "end": 67,
+                "begin": 19,
+                "end": 70,
                 "abridged": false
             }
         }
@@ -37,8 +34,8 @@
     "2": {
         "benchmarks": {
             "rendering.mobile": {
-                "begin": 67,
-                "end": 113,
+                "begin": 70,
+                "end": 118,
                 "abridged": false
             }
         }
@@ -46,8 +43,8 @@
     "3": {
         "benchmarks": {
             "rendering.mobile": {
-                "begin": 113,
-                "end": 198,
+                "begin": 118,
+                "end": 211,
                 "abridged": false
             }
         }
@@ -55,8 +52,8 @@
     "4": {
         "benchmarks": {
             "rendering.mobile": {
-                "begin": 198,
-                "end": 299,
+                "begin": 211,
+                "end": 312,
                 "abridged": false
             }
         }
@@ -64,8 +61,8 @@
     "5": {
         "benchmarks": {
             "rendering.mobile": {
-                "begin": 299,
-                "end": 358,
+                "begin": 312,
+                "end": 366,
                 "abridged": false
             }
         }
@@ -73,8 +70,8 @@
     "6": {
         "benchmarks": {
             "rendering.mobile": {
-                "begin": 358,
-                "end": 406,
+                "begin": 366,
+                "end": 419,
                 "abridged": false
             }
         }
@@ -82,7 +79,7 @@
     "7": {
         "benchmarks": {
             "rendering.mobile": {
-                "begin": 406,
+                "begin": 419,
                 "abridged": false
             },
             "speedometer": {
@@ -92,7 +89,7 @@
                 "abridged": false
             },
             "system_health.memory_desktop": {
-                "end": 27,
+                "end": 25,
                 "abridged": false
             }
         }
@@ -100,7 +97,7 @@
     "8": {
         "benchmarks": {
             "system_health.memory_desktop": {
-                "begin": 27,
+                "begin": 25,
                 "end": 50,
                 "abridged": false
             }
@@ -115,20 +112,20 @@
         }
     },
     "extra_infos": {
-        "num_stories": 522,
-        "predicted_min_shard_time": 1662.0,
+        "num_stories": 521,
+        "predicted_min_shard_time": 1731.0,
         "predicted_min_shard_index": 9,
-        "predicted_max_shard_time": 1707.0,
-        "predicted_max_shard_index": 7,
-        "shard #0": 1688.0,
-        "shard #1": 1700.0,
-        "shard #2": 1694.0,
-        "shard #3": 1702.0,
-        "shard #4": 1690.0,
-        "shard #5": 1697.0,
-        "shard #6": 1670.0,
-        "shard #7": 1707.0,
-        "shard #8": 1689.0,
-        "shard #9": 1662.0
+        "predicted_max_shard_time": 1866.0,
+        "predicted_max_shard_index": 8,
+        "shard #0": 1790.0,
+        "shard #1": 1789.0,
+        "shard #2": 1768.0,
+        "shard #3": 1793.0,
+        "shard #4": 1799.0,
+        "shard #5": 1762.0,
+        "shard #6": 1778.0,
+        "shard #7": 1747.0,
+        "shard #8": 1866.0,
+        "shard #9": 1731.0
     }
 }
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/fuchsia-perf-sherlock-fyi_map.json b/tools/perf/core/shard_maps/fuchsia-perf-sherlock-fyi_map.json
index db8a7d7..3dbe64c3 100644
--- a/tools/perf/core/shard_maps/fuchsia-perf-sherlock-fyi_map.json
+++ b/tools/perf/core/shard_maps/fuchsia-perf-sherlock-fyi_map.json
@@ -1,9 +1,6 @@
 {
     "0": {
         "benchmarks": {
-            "jetstream2": {
-                "abridged": false
-            },
             "media.mobile": {
                 "abridged": false
             },
@@ -29,7 +26,7 @@
         "benchmarks": {
             "rendering.mobile": {
                 "begin": 37,
-                "end": 121,
+                "end": 120,
                 "abridged": false
             }
         }
@@ -37,8 +34,8 @@
     "2": {
         "benchmarks": {
             "rendering.mobile": {
-                "begin": 121,
-                "end": 250,
+                "begin": 120,
+                "end": 251,
                 "abridged": false
             }
         }
@@ -46,7 +43,7 @@
     "3": {
         "benchmarks": {
             "rendering.mobile": {
-                "begin": 250,
+                "begin": 251,
                 "end": 346,
                 "abridged": false
             }
@@ -56,17 +53,12 @@
         "benchmarks": {
             "rendering.mobile": {
                 "begin": 346,
-                "end": 420,
                 "abridged": false
             }
         }
     },
     "5": {
         "benchmarks": {
-            "rendering.mobile": {
-                "begin": 420,
-                "abridged": false
-            },
             "speedometer": {
                 "abridged": false
             },
@@ -79,16 +71,16 @@
         }
     },
     "extra_infos": {
-        "num_stories": 522,
-        "predicted_min_shard_time": 1945.0,
-        "predicted_min_shard_index": 3,
-        "predicted_max_shard_time": 1977.0,
-        "predicted_max_shard_index": 5,
-        "shard #0": 1965.0,
-        "shard #1": 1964.0,
-        "shard #2": 1959.0,
-        "shard #3": 1945.0,
+        "num_stories": 521,
+        "predicted_min_shard_time": 1939.0,
+        "predicted_min_shard_index": 5,
+        "predicted_max_shard_time": 1972.0,
+        "predicted_max_shard_index": 3,
+        "shard #0": 1969.0,
+        "shard #1": 1956.0,
+        "shard #2": 1960.0,
+        "shard #3": 1972.0,
         "shard #4": 1964.0,
-        "shard #5": 1977.0
+        "shard #5": 1939.0
     }
 }
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/timing_data/fuchsia-perf-fyi_timing.json b/tools/perf/core/shard_maps/timing_data/fuchsia-perf-fyi_timing.json
index b9bbdef..7867a27 100644
--- a/tools/perf/core/shard_maps/timing_data/fuchsia-perf-fyi_timing.json
+++ b/tools/perf/core/shard_maps/timing_data/fuchsia-perf-fyi_timing.json
@@ -1,6 +1,6 @@
 [
     {
-        "duration": "10.0",
+        "duration": "11.0",
         "name": "media.mobile/mse.html?media=aac_audio.mp4"
     },
     {
@@ -8,7 +8,7 @@
         "name": "media.mobile/mse.html?media=aac_audio.mp4,h264_video.mp4"
     },
     {
-        "duration": "11.0",
+        "duration": "12.0",
         "name": "media.mobile/mse.html?media=h264_video.mp4"
     },
     {
@@ -44,7 +44,7 @@
         "name": "media.mobile/video.html?src=tulip2.mp4&busyjs"
     },
     {
-        "duration": "29.0",
+        "duration": "28.0",
         "name": "media.mobile/video.html?src=tulip2.ogg&type=audio"
     },
     {
@@ -64,107 +64,107 @@
         "name": "media.mobile/video.html?src=tulip2.vp9.webm_WiFi"
     },
     {
-        "duration": "41.0",
+        "duration": "45.0",
         "name": "rendering.mobile/accu_weather_2018"
     },
     {
-        "duration": "10.0",
+        "duration": "13.0",
         "name": "rendering.mobile/accu_weather_mobile_pinch_2018"
     },
     {
-        "duration": "31.0",
+        "duration": "34.0",
         "name": "rendering.mobile/amazon_2018"
     },
     {
-        "duration": "32.0",
+        "duration": "36.0",
         "name": "rendering.mobile/amazon_mobile_2018"
     },
     {
-        "duration": "23.0",
+        "duration": "26.0",
         "name": "rendering.mobile/analog_clock_svg"
     },
     {
-        "duration": "49.0",
+        "duration": "52.0",
         "name": "rendering.mobile/androidpolice_mobile_2018"
     },
     {
-        "duration": "29.0",
+        "duration": "33.0",
         "name": "rendering.mobile/animometer_webgl"
     },
     {
-        "duration": "26.0",
+        "duration": "29.0",
         "name": "rendering.mobile/animometer_webgl_attrib_arrays"
     },
     {
-        "duration": "34.0",
+        "duration": "36.0",
         "name": "rendering.mobile/animometer_webgl_multi_draw"
     },
     {
-        "duration": "41.0",
+        "duration": "43.0",
         "name": "rendering.mobile/aquarium"
     },
     {
-        "duration": "18.0",
+        "duration": "20.0",
         "name": "rendering.mobile/aquarium_20k"
     },
     {
-        "duration": "38.0",
+        "duration": "39.0",
         "name": "rendering.mobile/background_color_animation"
     },
     {
-        "duration": "31.0",
+        "duration": "33.0",
         "name": "rendering.mobile/background_color_animation_with_gradient"
     },
     {
-        "duration": "34.0",
+        "duration": "35.0",
         "name": "rendering.mobile/baidu_mobile_2018"
     },
     {
-        "duration": "38.0",
+        "duration": "40.0",
         "name": "rendering.mobile/balls_css_key_frame_animations"
     },
     {
-        "duration": "43.0",
+        "duration": "45.0",
         "name": "rendering.mobile/balls_css_key_frame_animations_composited_transform"
     },
     {
-        "duration": "32.0",
+        "duration": "34.0",
         "name": "rendering.mobile/balls_css_transition_2_properties"
     },
     {
-        "duration": "32.0",
+        "duration": "33.0",
         "name": "rendering.mobile/balls_css_transition_40_properties"
     },
     {
-        "duration": "32.0",
+        "duration": "33.0",
         "name": "rendering.mobile/balls_css_transition_all_properties"
     },
     {
-        "duration": "32.0",
+        "duration": "33.0",
         "name": "rendering.mobile/balls_javascript_canvas"
     },
     {
-        "duration": "34.0",
+        "duration": "35.0",
         "name": "rendering.mobile/balls_javascript_css"
     },
     {
-        "duration": "18.0",
+        "duration": "19.0",
         "name": "rendering.mobile/balls_svg_animations"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/basic_stream"
     },
     {
-        "duration": "31.0",
+        "duration": "32.0",
         "name": "rendering.mobile/bing_mobile_2018"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/blob"
     },
     {
-        "duration": "18.0",
+        "duration": "19.0",
         "name": "rendering.mobile/blogspot_2018"
     },
     {
@@ -172,15 +172,15 @@
         "name": "rendering.mobile/blogspot_mobile_2018"
     },
     {
-        "duration": "27.0",
+        "duration": "28.0",
         "name": "rendering.mobile/blur_rotating_background"
     },
     {
-        "duration": "45.0",
+        "duration": "47.0",
         "name": "rendering.mobile/boingboing_mobile_2018"
     },
     {
-        "duration": "44.0",
+        "duration": "45.0",
         "name": "rendering.mobile/booking.com_2018"
     },
     {
@@ -188,19 +188,19 @@
         "name": "rendering.mobile/booking.com_mobile_2018"
     },
     {
-        "duration": "32.0",
+        "duration": "33.0",
         "name": "rendering.mobile/bouncing_balls_15"
     },
     {
-        "duration": "46.0",
+        "duration": "47.0",
         "name": "rendering.mobile/bouncing_balls_shadow"
     },
     {
-        "duration": "33.0",
+        "duration": "34.0",
         "name": "rendering.mobile/bouncing_clipped_rectangles"
     },
     {
-        "duration": "32.0",
+        "duration": "33.0",
         "name": "rendering.mobile/bouncing_gradient_circles"
     },
     {
@@ -208,15 +208,15 @@
         "name": "rendering.mobile/bouncing_png_images"
     },
     {
-        "duration": "38.0",
+        "duration": "39.0",
         "name": "rendering.mobile/bouncing_svg_images"
     },
     {
-        "duration": "33.0",
+        "duration": "34.0",
         "name": "rendering.mobile/camera_to_webgl"
     },
     {
-        "duration": "32.0",
+        "duration": "33.0",
         "name": "rendering.mobile/canvas2d_to_texture.html"
     },
     {
@@ -248,15 +248,15 @@
         "name": "rendering.mobile/canvas_90000_pixels_per_second"
     },
     {
-        "duration": "31.0",
+        "duration": "32.0",
         "name": "rendering.mobile/canvas_animation_no_clear"
     },
     {
-        "duration": "32.0",
+        "duration": "33.0",
         "name": "rendering.mobile/canvas_arcs"
     },
     {
-        "duration": "34.0",
+        "duration": "35.0",
         "name": "rendering.mobile/canvas_font_cycler"
     },
     {
@@ -268,11 +268,11 @@
         "name": "rendering.mobile/canvas_to_blob"
     },
     {
-        "duration": "31.0",
+        "duration": "32.0",
         "name": "rendering.mobile/canvas_to_canvas_draw"
     },
     {
-        "duration": "44.0",
+        "duration": "45.0",
         "name": "rendering.mobile/capitolvolkswagen_mobile_2018"
     },
     {
@@ -292,35 +292,35 @@
         "name": "rendering.mobile/card_flying"
     },
     {
-        "duration": "35.0",
+        "duration": "36.0",
         "name": "rendering.mobile/cc_poster_circle"
     },
     {
-        "duration": "32.0",
+        "duration": "33.0",
         "name": "rendering.mobile/cc_scroll_text_only"
     },
     {
-        "duration": "35.0",
+        "duration": "36.0",
         "name": "rendering.mobile/chip_tune"
     },
     {
-        "duration": "64.0",
+        "duration": "65.0",
         "name": "rendering.mobile/cnn_2018"
     },
     {
-        "duration": "18.0",
+        "duration": "19.0",
         "name": "rendering.mobile/cnn_article_mobile_2018"
     },
     {
-        "duration": "60.0",
+        "duration": "61.0",
         "name": "rendering.mobile/cnn_mobile_2018"
     },
     {
-        "duration": "18.0",
+        "duration": "19.0",
         "name": "rendering.mobile/cnn_mobile_pinch_2018"
     },
     {
-        "duration": "55.0",
+        "duration": "56.0",
         "name": "rendering.mobile/cnn_pathological_2018"
     },
     {
@@ -336,11 +336,11 @@
         "name": "rendering.mobile/crafty_mind"
     },
     {
-        "duration": "39.0",
+        "duration": "40.0",
         "name": "rendering.mobile/css_animations_many_keyframes"
     },
     {
-        "duration": "43.0",
+        "duration": "41.0",
         "name": "rendering.mobile/css_animations_simultaneous_inline_style"
     },
     {
@@ -356,43 +356,43 @@
         "name": "rendering.mobile/css_animations_simultaneous_updating_class"
     },
     {
-        "duration": "37.0",
+        "duration": "39.0",
         "name": "rendering.mobile/css_animations_staggered_infinite_iterations"
     },
     {
-        "duration": "39.0",
+        "duration": "40.0",
         "name": "rendering.mobile/css_animations_staggered_inline_style"
     },
     {
-        "duration": "39.0",
+        "duration": "40.0",
         "name": "rendering.mobile/css_animations_staggered_new_element"
     },
     {
-        "duration": "40.0",
+        "duration": "41.0",
         "name": "rendering.mobile/css_animations_staggered_style_element"
     },
     {
-        "duration": "39.0",
+        "duration": "40.0",
         "name": "rendering.mobile/css_animations_staggered_updating_class"
     },
     {
-        "duration": "39.0",
+        "duration": "40.0",
         "name": "rendering.mobile/css_animations_triggered_inline_style"
     },
     {
-        "duration": "39.0",
+        "duration": "40.0",
         "name": "rendering.mobile/css_animations_triggered_new_element"
     },
     {
-        "duration": "38.0",
+        "duration": "39.0",
         "name": "rendering.mobile/css_animations_triggered_style_element"
     },
     {
-        "duration": "39.0",
+        "duration": "40.0",
         "name": "rendering.mobile/css_animations_triggered_updating_class"
     },
     {
-        "duration": "34.0",
+        "duration": "35.0",
         "name": "rendering.mobile/css_opacity_plus_n_layers_0"
     },
     {
@@ -404,143 +404,143 @@
         "name": "rendering.mobile/css_opacity_plus_n_layers_99"
     },
     {
-        "duration": "37.0",
+        "duration": "38.0",
         "name": "rendering.mobile/css_transitions_inline_style"
     },
     {
-        "duration": "37.0",
+        "duration": "38.0",
         "name": "rendering.mobile/css_transitions_new_element"
     },
     {
-        "duration": "38.0",
+        "duration": "39.0",
         "name": "rendering.mobile/css_transitions_staggered_inline_style"
     },
     {
-        "duration": "38.0",
+        "duration": "39.0",
         "name": "rendering.mobile/css_transitions_staggered_new_element"
     },
     {
-        "duration": "38.0",
+        "duration": "39.0",
         "name": "rendering.mobile/css_transitions_staggered_style_element"
     },
     {
-        "duration": "38.0",
+        "duration": "39.0",
         "name": "rendering.mobile/css_transitions_staggered_updating_class"
     },
     {
-        "duration": "37.0",
+        "duration": "38.0",
         "name": "rendering.mobile/css_transitions_style_element"
     },
     {
-        "duration": "38.0",
+        "duration": "39.0",
         "name": "rendering.mobile/css_transitions_triggered_inline_style"
     },
     {
-        "duration": "38.0",
+        "duration": "39.0",
         "name": "rendering.mobile/css_transitions_triggered_new_element"
     },
     {
-        "duration": "37.0",
+        "duration": "39.0",
         "name": "rendering.mobile/css_transitions_triggered_style_element"
     },
     {
-        "duration": "38.0",
+        "duration": "39.0",
         "name": "rendering.mobile/css_transitions_triggered_updating_class"
     },
     {
-        "duration": "37.0",
+        "duration": "38.0",
         "name": "rendering.mobile/css_transitions_updating_class"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/css_value_type_color"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/css_value_type_filter"
     },
     {
-        "duration": "37.0",
+        "duration": "38.0",
         "name": "rendering.mobile/css_value_type_length"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/css_value_type_length_complex"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/css_value_type_length_simple"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/css_value_type_path"
     },
     {
-        "duration": "35.0",
+        "duration": "36.0",
         "name": "rendering.mobile/css_value_type_shadow"
     },
     {
-        "duration": "37.0",
+        "duration": "38.0",
         "name": "rendering.mobile/css_value_type_transform_complex"
     },
     {
-        "duration": "37.0",
+        "duration": "38.0",
         "name": "rendering.mobile/css_value_type_transform_simple"
     },
     {
-        "duration": "42.0",
+        "duration": "43.0",
         "name": "rendering.mobile/deviantart_mobile_2018"
     },
     {
-        "duration": "22.0",
+        "duration": "23.0",
         "name": "rendering.mobile/digg_mobile_2018"
     },
     {
-        "duration": "22.0",
+        "duration": "23.0",
         "name": "rendering.mobile/docs_paper.html"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/docs_resume.html"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/docs_table.html"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/draw_image"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/draw_image_not_pixel_aligned"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/dynamic_canvas_to_hw_accelerated_canvas.html"
     },
     {
-        "duration": "41.0",
+        "duration": "42.0",
         "name": "rendering.mobile/dynamic_cube_map"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/dynamic_webgl_to_hw_accelerated_canvas.html"
     },
     {
-        "duration": "39.0",
+        "duration": "40.0",
         "name": "rendering.mobile/earth"
     },
     {
-        "duration": "43.0",
+        "duration": "44.0",
         "name": "rendering.mobile/ebay_2018"
     },
     {
-        "duration": "34.0",
+        "duration": "35.0",
         "name": "rendering.mobile/ebay_mobile_2018"
     },
     {
-        "duration": "22.0",
+        "duration": "23.0",
         "name": "rendering.mobile/ebay_mobile_pinch_2018"
     },
     {
@@ -548,11 +548,11 @@
         "name": "rendering.mobile/ebay_scroll_2018"
     },
     {
-        "duration": "40.0",
+        "duration": "37.0",
         "name": "rendering.mobile/effect_games"
     },
     {
-        "duration": "22.0",
+        "duration": "23.0",
         "name": "rendering.mobile/espn_2018"
     },
     {
@@ -560,39 +560,39 @@
         "name": "rendering.mobile/espn_mobile_2018"
     },
     {
-        "duration": "40.0",
+        "duration": "36.0",
         "name": "rendering.mobile/espn_pathological_2018"
     },
     {
-        "duration": "37.0",
+        "duration": "35.0",
         "name": "rendering.mobile/extra_large_texture_uploads"
     },
     {
-        "duration": "22.0",
+        "duration": "19.0",
         "name": "rendering.mobile/facebook_2018"
     },
     {
-        "duration": "22.0",
+        "duration": "19.0",
         "name": "rendering.mobile/facebook_mobile_2018"
     },
     {
-        "duration": "36.0",
+        "duration": "32.0",
         "name": "rendering.mobile/falling_particle_simulation_cpu.html"
     },
     {
-        "duration": "36.0",
+        "duration": "33.0",
         "name": "rendering.mobile/falling_particle_simulation_gpu.html"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/famo_us_twitter_demo"
     },
     {
-        "duration": "36.0",
+        "duration": "33.0",
         "name": "rendering.mobile/fill_clear_rect.html"
     },
     {
-        "duration": "36.0",
+        "duration": "33.0",
         "name": "rendering.mobile/fill_shapes"
     },
     {
@@ -640,7 +640,7 @@
         "name": "rendering.mobile/google_image_search_mobile_2018"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/google_news_ios"
     },
     {
@@ -668,7 +668,7 @@
         "name": "rendering.mobile/google_web_search_mobile_2018"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "rendering.mobile/gpu_bound_shader.html"
     },
     {
@@ -676,7 +676,7 @@
         "name": "rendering.mobile/gsp.ro_mobile_2018"
     },
     {
-        "duration": "18.0",
+        "duration": "20.0",
         "name": "rendering.mobile/guardian_pathological_2018"
     },
     {
@@ -704,15 +704,15 @@
         "name": "rendering.mobile/hw_accelerated_canvas_to_sw_canvas.html"
     },
     {
-        "duration": "10.0",
+        "duration": "13.0",
         "name": "rendering.mobile/idle_power_animated_gif"
     },
     {
-        "duration": "18.0",
+        "duration": "19.0",
         "name": "rendering.mobile/idle_power_blank"
     },
     {
-        "duration": "18.0",
+        "duration": "19.0",
         "name": "rendering.mobile/idle_power_css_animation"
     },
     {
@@ -728,11 +728,11 @@
         "name": "rendering.mobile/idle_power_set_timetout"
     },
     {
-        "duration": "18.0",
+        "duration": "19.0",
         "name": "rendering.mobile/ie_chalkboard"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/ie_pirate_mark"
     },
     {
@@ -856,11 +856,11 @@
         "name": "rendering.mobile/linkedin_pathological_2018"
     },
     {
-        "duration": "16.0",
+        "duration": "17.0",
         "name": "rendering.mobile/list_animation_simple"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/list_recycle_transform"
     },
     {
@@ -872,7 +872,7 @@
         "name": "rendering.mobile/main_0fps_impl_60fps_no_update"
     },
     {
-        "duration": "19.0",
+        "duration": "18.0",
         "name": "rendering.mobile/main_0fps_impl_60fps_no_update_jank"
     },
     {
@@ -904,7 +904,7 @@
         "name": "rendering.mobile/main_60fps_impl_60fps"
     },
     {
-        "duration": "19.0",
+        "duration": "18.0",
         "name": "rendering.mobile/main_60fps_impl_60fps_no_update"
     },
     {
@@ -932,15 +932,15 @@
         "name": "rendering.mobile/man_in_blue"
     },
     {
-        "duration": "36.0",
+        "duration": "35.0",
         "name": "rendering.mobile/many_images"
     },
     {
-        "duration": "27.0",
+        "duration": "26.0",
         "name": "rendering.mobile/many_planets_deep"
     },
     {
-        "duration": "31.0",
+        "duration": "30.0",
         "name": "rendering.mobile/maps_perf_test"
     },
     {
@@ -948,7 +948,7 @@
         "name": "rendering.mobile/mask_transition_animation"
     },
     {
-        "duration": "21.0",
+        "duration": "23.0",
         "name": "rendering.mobile/masonry"
     },
     {
@@ -960,7 +960,7 @@
         "name": "rendering.mobile/megi_dish"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/microgame_fps"
     },
     {
@@ -968,7 +968,7 @@
         "name": "rendering.mobile/microsoft_asteroid_belt"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/microsoft_fireflies"
     },
     {
@@ -1000,7 +1000,7 @@
         "name": "rendering.mobile/microsoft_worker_fountains"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/mix_10k"
     },
     {
@@ -1020,15 +1020,15 @@
         "name": "rendering.mobile/mix_blend_mode_animation_screen"
     },
     {
-        "duration": "51.0",
+        "duration": "53.0",
         "name": "rendering.mobile/mlb_mobile_2018"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/mobile_news_sandbox"
     },
     {
-        "duration": "24.0",
+        "duration": "25.0",
         "name": "rendering.mobile/motion_mark_canvas_fill_shapes"
     },
     {
@@ -1036,127 +1036,127 @@
         "name": "rendering.mobile/motion_mark_canvas_stroke_shapes"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_anim_design_15"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_anim_focus_25"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_anim_images_50"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_anim_leaves_250"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_anim_multiply_175"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_anim_suits_125"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_html_composited_transforms_125"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_html_css_bouncing_blend_circles_25"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_html_css_bouncing_circles_250"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_html_css_bouncing_clipped_rects_100"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_html_css_bouncing_filter_circles_15"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_html_css_bouncing_gradient_circles_250"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_html_css_bouncing_svg_images_50"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_html_css_bouncing_tagged_images_225"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_html_dom_particles_svg_masks_25"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_html_focus_20_15"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_html_leaves_20_50"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_ramp_canvas_arcs"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_ramp_canvas_lines"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_ramp_design"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_ramp_images"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_ramp_leaves"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_ramp_multiply"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_ramp_paths"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_ramp_suits"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_svg_bouncing_circles_250"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_svg_bouncing_clipped_rects_100"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_svg_bouncing_gradient_circles_200"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_svg_bouncing_png_images_200"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/motionmark_svg_bouncing_svg_images_50"
     },
     {
-        "duration": "27.0",
+        "duration": "28.0",
         "name": "rendering.mobile/new_tilings"
     },
     {
@@ -1180,15 +1180,15 @@
         "name": "rendering.mobile/no_update_compositor_animation_with_janky_main_animation"
     },
     {
-        "duration": "35.0",
+        "duration": "36.0",
         "name": "rendering.mobile/non_opaque_background_compositor_thread_scrolling_00050_pixels_per_second"
     },
     {
-        "duration": "35.0",
+        "duration": "36.0",
         "name": "rendering.mobile/non_opaque_background_main_thread_scrolling_00050_pixels_per_second"
     },
     {
-        "duration": "25.0",
+        "duration": "26.0",
         "name": "rendering.mobile/nvidia_vertex_buffer_object"
     },
     {
@@ -1196,11 +1196,11 @@
         "name": "rendering.mobile/nyc_gov_scroll_2018"
     },
     {
-        "duration": "54.0",
+        "duration": "56.0",
         "name": "rendering.mobile/nytimes_mobile_2018"
     },
     {
-        "duration": "47.0",
+        "duration": "50.0",
         "name": "rendering.mobile/nytimes_scroll_2018"
     },
     {
@@ -1208,15 +1208,15 @@
         "name": "rendering.mobile/off_screen_main_60fps"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/off_screen_main_60fps_jank"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/offscreen_animation_no_damage"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "rendering.mobile/overlay_background_color_css_transitions_page"
     },
     {
@@ -1228,11 +1228,11 @@
         "name": "rendering.mobile/parallax_effect"
     },
     {
-        "duration": "26.0",
+        "duration": "27.0",
         "name": "rendering.mobile/particles"
     },
     {
-        "duration": "32.0",
+        "duration": "33.0",
         "name": "rendering.mobile/pbs_pathological_2018"
     },
     {
@@ -1240,7 +1240,7 @@
         "name": "rendering.mobile/physical_simulation"
     },
     {
-        "duration": "24.0",
+        "duration": "25.0",
         "name": "rendering.mobile/pinterest_2018"
     },
     {
@@ -1264,7 +1264,7 @@
         "name": "rendering.mobile/raf"
     },
     {
-        "duration": "20.0",
+        "duration": "21.0",
         "name": "rendering.mobile/raf_animation"
     },
     {
@@ -1276,7 +1276,7 @@
         "name": "rendering.mobile/raf_touch_animation"
     },
     {
-        "duration": "40.0",
+        "duration": "41.0",
         "name": "rendering.mobile/recode_pathological_2018"
     },
     {
@@ -1324,7 +1324,7 @@
         "name": "rendering.mobile/simple_touch_drag"
     },
     {
-        "duration": "62.0",
+        "duration": "61.0",
         "name": "rendering.mobile/skelebuddies_wasm_2020"
     },
     {
@@ -1352,7 +1352,7 @@
         "name": "rendering.mobile/static_webgl_to_hw_accelerated_canvas.html"
     },
     {
-        "duration": "9.0",
+        "duration": "10.0",
         "name": "rendering.mobile/sticky_using_webkit"
     },
     {
@@ -1368,15 +1368,15 @@
         "name": "rendering.mobile/swipe_to_dismiss"
     },
     {
-        "duration": "35.0",
+        "duration": "32.0",
         "name": "rendering.mobile/sync_scroll_offset"
     },
     {
-        "duration": "58.0",
+        "duration": "56.0",
         "name": "rendering.mobile/techcrunch_2018"
     },
     {
-        "duration": "58.0",
+        "duration": "59.0",
         "name": "rendering.mobile/techcrunch_mobile_2018"
     },
     {
@@ -1436,7 +1436,7 @@
         "name": "rendering.mobile/text_constant_full_page_raster_90000_pixels_per_second"
     },
     {
-        "duration": "33.0",
+        "duration": "32.0",
         "name": "rendering.mobile/text_fling_05000_pixels_per_second"
     },
     {
@@ -1504,7 +1504,7 @@
         "name": "rendering.mobile/theverge_mobile_2018"
     },
     {
-        "duration": "38.0",
+        "duration": "40.0",
         "name": "rendering.mobile/throughput_scrolling_active_handler"
     },
     {
@@ -1528,23 +1528,23 @@
         "name": "rendering.mobile/toBlob_duration.html"
     },
     {
-        "duration": "34.0",
+        "duration": "35.0",
         "name": "rendering.mobile/toBlob_duration_jpeg.html"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/toBlob_small_canvas_in_worker.html"
     },
     {
-        "duration": "30.0",
+        "duration": "31.0",
         "name": "rendering.mobile/touch_handler_scrolling"
     },
     {
-        "duration": "33.0",
+        "duration": "34.0",
         "name": "rendering.mobile/transfer_from_imageBitmap.html"
     },
     {
-        "duration": "33.0",
+        "duration": "34.0",
         "name": "rendering.mobile/transform_transitions"
     },
     {
@@ -1568,11 +1568,11 @@
         "name": "rendering.mobile/twitter_mobile_2018"
     },
     {
-        "duration": "30.0",
+        "duration": "31.0",
         "name": "rendering.mobile/update_history_state"
     },
     {
-        "duration": "50.0",
+        "duration": "51.0",
         "name": "rendering.mobile/usatoday_mobile_2018"
     },
     {
@@ -1604,27 +1604,27 @@
         "name": "rendering.mobile/video_to_texture"
     },
     {
-        "duration": "33.0",
+        "duration": "34.0",
         "name": "rendering.mobile/web_animation_value_type_color"
     },
     {
-        "duration": "35.0",
+        "duration": "36.0",
         "name": "rendering.mobile/web_animation_value_type_length_3d"
     },
     {
-        "duration": "33.0",
+        "duration": "34.0",
         "name": "rendering.mobile/web_animation_value_type_length_complex"
     },
     {
-        "duration": "33.0",
+        "duration": "34.0",
         "name": "rendering.mobile/web_animation_value_type_length_simple"
     },
     {
-        "duration": "33.0",
+        "duration": "34.0",
         "name": "rendering.mobile/web_animation_value_type_path"
     },
     {
-        "duration": "33.0",
+        "duration": "34.0",
         "name": "rendering.mobile/web_animation_value_type_shadow"
     },
     {
@@ -1648,7 +1648,7 @@
         "name": "rendering.mobile/web_animations_simultaneous"
     },
     {
-        "duration": "36.0",
+        "duration": "37.0",
         "name": "rendering.mobile/web_animations_staggered_chaining"
     },
     {
@@ -1664,15 +1664,15 @@
         "name": "rendering.mobile/webgl_to_texture"
     },
     {
-        "duration": "27.0",
+        "duration": "28.0",
         "name": "rendering.mobile/webp_decoding_rgb_and_gpu_rasterization"
     },
     {
-        "duration": "27.0",
+        "duration": "28.0",
         "name": "rendering.mobile/webp_decoding_yuv_and_gpu_rasterization"
     },
     {
-        "duration": "40.0",
+        "duration": "42.0",
         "name": "rendering.mobile/wikipedia_2018"
     },
     {
@@ -1680,19 +1680,19 @@
         "name": "rendering.mobile/wikipedia_delayed_scroll_start_2018"
     },
     {
-        "duration": "36.0",
+        "duration": "35.0",
         "name": "rendering.mobile/wikipedia_mobile_2018"
     },
     {
-        "duration": "20.0",
+        "duration": "18.0",
         "name": "rendering.mobile/wordpress_2018"
     },
     {
-        "duration": "40.0",
+        "duration": "38.0",
         "name": "rendering.mobile/wordpress_mobile_2018"
     },
     {
-        "duration": "48.0",
+        "duration": "46.0",
         "name": "rendering.mobile/worldjournal_mobile_2018"
     },
     {
@@ -1700,7 +1700,7 @@
         "name": "rendering.mobile/wow_wiki_pathological_2018"
     },
     {
-        "duration": "74.0",
+        "duration": "73.0",
         "name": "rendering.mobile/wowwiki_mobile_2018"
     },
     {
@@ -1708,7 +1708,7 @@
         "name": "rendering.mobile/wsj_mobile_2018"
     },
     {
-        "duration": "47.0",
+        "duration": "46.0",
         "name": "rendering.mobile/yahoo_answers_2018"
     },
     {
@@ -1716,11 +1716,11 @@
         "name": "rendering.mobile/yahoo_answers_mobile_2018"
     },
     {
-        "duration": "34.0",
+        "duration": "33.0",
         "name": "rendering.mobile/yahoo_news_2018"
     },
     {
-        "duration": "33.0",
+        "duration": "32.0",
         "name": "rendering.mobile/yahoo_news_mobile_2018"
     },
     {
@@ -1740,7 +1740,7 @@
         "name": "rendering.mobile/youtube_mobile_2018"
     },
     {
-        "duration": "41.0",
+        "duration": "40.0",
         "name": "rendering.mobile/zdnet_pathological_2018"
     },
     {
@@ -1748,6 +1748,14 @@
         "name": "rendering.mobile/zoom_in_animation"
     },
     {
+        "duration": "265.0",
+        "name": "speedometer/http://browserbench.org/Speedometer/"
+    },
+    {
+        "duration": "447.0",
+        "name": "speedometer2/Speedometer2"
+    },
+    {
         "duration": "1.0",
         "name": "system_health.memory_desktop/browse:media:googleplaystore:2021"
     },
@@ -1756,23 +1764,23 @@
         "name": "system_health.memory_desktop/browse:media:imgur"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/browse:media:pinterest:2018"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/browse:media:tumblr:2018"
     },
     {
-        "duration": "91.0",
+        "duration": "92.0",
         "name": "system_health.memory_desktop/browse:media:youtube:2019"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/browse:media:youtubetv:2019"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/browse:media:youtubetv_watch:2020"
     },
     {
@@ -1784,15 +1792,15 @@
         "name": "system_health.memory_desktop/browse:news:flipboard:2020"
     },
     {
-        "duration": "69.0",
+        "duration": "66.0",
         "name": "system_health.memory_desktop/browse:news:hackernews:2020"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/browse:news:nytimes:2020"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/browse:news:reddit:2020"
     },
     {
@@ -1808,11 +1816,11 @@
         "name": "system_health.memory_desktop/browse:social:facebook_infinite_scroll:2018"
     },
     {
-        "duration": "68.0",
+        "duration": "69.0",
         "name": "system_health.memory_desktop/browse:social:tumblr_infinite_scroll:2018"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/browse:social:twitter:2018"
     },
     {
@@ -1852,11 +1860,11 @@
         "name": "system_health.memory_desktop/browse:tools:maps:2019"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/browse:tools:photoshop:2021"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/browse:tools:photoshop_warm:2021"
     },
     {
@@ -1892,7 +1900,7 @@
         "name": "system_health.memory_desktop/load:games:miniclip:2018"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/load:games:spychase:2018"
     },
     {
@@ -1908,7 +1916,7 @@
         "name": "system_health.memory_desktop/load:media:facebook_feed:desktop:2020"
     },
     {
-        "duration": "20.0",
+        "duration": "21.0",
         "name": "system_health.memory_desktop/load:media:facebook_photos:2018"
     },
     {
@@ -1920,7 +1928,7 @@
         "name": "system_health.memory_desktop/load:media:flickr:2018"
     },
     {
-        "duration": "22.0",
+        "duration": "23.0",
         "name": "system_health.memory_desktop/load:media:google_images:2018"
     },
     {
@@ -1932,11 +1940,11 @@
         "name": "system_health.memory_desktop/load:media:soundcloud:2018"
     },
     {
-        "duration": "30.0",
+        "duration": "31.0",
         "name": "system_health.memory_desktop/load:media:youtube:2018"
     },
     {
-        "duration": "19.0",
+        "duration": "20.0",
         "name": "system_health.memory_desktop/load:media:youtubelivingroom:2020"
     },
     {
@@ -1948,23 +1956,23 @@
         "name": "system_health.memory_desktop/load:news:cnn:2020"
     },
     {
-        "duration": "25.0",
+        "duration": "26.0",
         "name": "system_health.memory_desktop/load:news:flipboard"
     },
     {
-        "duration": "18.0",
+        "duration": "19.0",
         "name": "system_health.memory_desktop/load:news:hackernews:2018"
     },
     {
-        "duration": "45.0",
+        "duration": "48.0",
         "name": "system_health.memory_desktop/load:news:nytimes:2018"
     },
     {
-        "duration": "27.0",
+        "duration": "26.0",
         "name": "system_health.memory_desktop/load:news:qq:2018"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/load:news:reddit:2018"
     },
     {
@@ -1976,15 +1984,15 @@
         "name": "system_health.memory_desktop/load:search:amazon:2018"
     },
     {
-        "duration": "30.0",
+        "duration": "28.0",
         "name": "system_health.memory_desktop/load:search:baidu:2018"
     },
     {
-        "duration": "32.0",
+        "duration": "33.0",
         "name": "system_health.memory_desktop/load:search:ebay:2018"
     },
     {
-        "duration": "39.0",
+        "duration": "38.0",
         "name": "system_health.memory_desktop/load:search:flipkart:2018"
     },
     {
@@ -2000,7 +2008,7 @@
         "name": "system_health.memory_desktop/load:search:yahoo:2018"
     },
     {
-        "duration": "19.0",
+        "duration": "20.0",
         "name": "system_health.memory_desktop/load:search:yandex:2018"
     },
     {
@@ -2008,11 +2016,11 @@
         "name": "system_health.memory_desktop/load:social:instagram:2018"
     },
     {
-        "duration": "16.0",
+        "duration": "17.0",
         "name": "system_health.memory_desktop/load:social:pinterest:2019"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "system_health.memory_desktop/load:social:vk:2018"
     },
     {
@@ -2020,7 +2028,7 @@
         "name": "system_health.memory_desktop/load:tools:chat:2020"
     },
     {
-        "duration": "47.0",
+        "duration": "48.0",
         "name": "system_health.memory_desktop/load:tools:docs:2019"
     },
     {
@@ -2036,7 +2044,7 @@
         "name": "system_health.memory_desktop/load:tools:stackoverflow:2018"
     },
     {
-        "duration": "30.0",
+        "duration": "31.0",
         "name": "system_health.memory_desktop/load:tools:weather:2019"
     },
     {
@@ -2048,19 +2056,19 @@
         "name": "system_health.memory_desktop/load_accessibility:shopping:amazon:2018"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/long_running:tools:gmail-background"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/long_running:tools:gmail-foreground"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/multitab:misc:typical24"
     },
     {
-        "duration": "4.0",
+        "duration": "5.0",
         "name": "system_health.memory_desktop/multitab:misc:typical24:2018"
     },
     {
@@ -2068,7 +2076,7 @@
         "name": "system_health.memory_desktop/play:media:google_play_music"
     },
     {
-        "duration": "50.0",
+        "duration": "51.0",
         "name": "system_health.memory_desktop/play:media:soundcloud:2018"
     },
     {
diff --git a/tools/perf/core/shard_maps/timing_data/fuchsia-perf-sherlock-fyi_timing.json b/tools/perf/core/shard_maps/timing_data/fuchsia-perf-sherlock-fyi_timing.json
index 13968f7..f1a8876 100644
--- a/tools/perf/core/shard_maps/timing_data/fuchsia-perf-sherlock-fyi_timing.json
+++ b/tools/perf/core/shard_maps/timing_data/fuchsia-perf-sherlock-fyi_timing.json
@@ -44,7 +44,7 @@
         "name": "media.mobile/video.html?src=tulip2.mp4&busyjs"
     },
     {
-        "duration": "26.0",
+        "duration": "25.0",
         "name": "media.mobile/video.html?src=tulip2.ogg&type=audio"
     },
     {
@@ -72,7 +72,7 @@
         "name": "rendering.mobile/accu_weather_mobile_pinch_2018"
     },
     {
-        "duration": "26.0",
+        "duration": "27.0",
         "name": "rendering.mobile/amazon_2018"
     },
     {
@@ -84,7 +84,7 @@
         "name": "rendering.mobile/analog_clock_svg"
     },
     {
-        "duration": "37.0",
+        "duration": "38.0",
         "name": "rendering.mobile/androidpolice_mobile_2018"
     },
     {
@@ -92,7 +92,7 @@
         "name": "rendering.mobile/animometer_webgl"
     },
     {
-        "duration": "24.0",
+        "duration": "25.0",
         "name": "rendering.mobile/animometer_webgl_attrib_arrays"
     },
     {
@@ -100,7 +100,7 @@
         "name": "rendering.mobile/animometer_webgl_multi_draw"
     },
     {
-        "duration": "28.0",
+        "duration": "29.0",
         "name": "rendering.mobile/aquarium"
     },
     {
@@ -108,11 +108,11 @@
         "name": "rendering.mobile/aquarium_20k"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "rendering.mobile/background_color_animation"
     },
     {
-        "duration": "21.0",
+        "duration": "22.0",
         "name": "rendering.mobile/background_color_animation_with_gradient"
     },
     {
@@ -120,23 +120,23 @@
         "name": "rendering.mobile/baidu_mobile_2018"
     },
     {
-        "duration": "27.0",
+        "duration": "28.0",
         "name": "rendering.mobile/balls_css_key_frame_animations"
     },
     {
-        "duration": "32.0",
+        "duration": "33.0",
         "name": "rendering.mobile/balls_css_key_frame_animations_composited_transform"
     },
     {
-        "duration": "22.0",
+        "duration": "23.0",
         "name": "rendering.mobile/balls_css_transition_2_properties"
     },
     {
-        "duration": "22.0",
+        "duration": "23.0",
         "name": "rendering.mobile/balls_css_transition_40_properties"
     },
     {
-        "duration": "22.0",
+        "duration": "23.0",
         "name": "rendering.mobile/balls_css_transition_all_properties"
     },
     {
@@ -152,7 +152,7 @@
         "name": "rendering.mobile/balls_svg_animations"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/basic_stream"
     },
     {
@@ -168,7 +168,7 @@
         "name": "rendering.mobile/blogspot_2018"
     },
     {
-        "duration": "19.0",
+        "duration": "20.0",
         "name": "rendering.mobile/blogspot_mobile_2018"
     },
     {
@@ -188,11 +188,11 @@
         "name": "rendering.mobile/booking.com_mobile_2018"
     },
     {
-        "duration": "21.0",
+        "duration": "22.0",
         "name": "rendering.mobile/bouncing_balls_15"
     },
     {
-        "duration": "34.0",
+        "duration": "35.0",
         "name": "rendering.mobile/bouncing_balls_shadow"
     },
     {
@@ -204,15 +204,15 @@
         "name": "rendering.mobile/bouncing_gradient_circles"
     },
     {
-        "duration": "21.0",
+        "duration": "22.0",
         "name": "rendering.mobile/bouncing_png_images"
     },
     {
-        "duration": "27.0",
+        "duration": "28.0",
         "name": "rendering.mobile/bouncing_svg_images"
     },
     {
-        "duration": "25.0",
+        "duration": "26.0",
         "name": "rendering.mobile/camera_to_webgl"
     },
     {
@@ -220,27 +220,27 @@
         "name": "rendering.mobile/canvas2d_to_texture.html"
     },
     {
-        "duration": "33.0",
+        "duration": "34.0",
         "name": "rendering.mobile/canvas_05000_pixels_per_second"
     },
     {
-        "duration": "31.0",
+        "duration": "32.0",
         "name": "rendering.mobile/canvas_10000_pixels_per_second"
     },
     {
-        "duration": "28.0",
+        "duration": "29.0",
         "name": "rendering.mobile/canvas_20000_pixels_per_second"
     },
     {
-        "duration": "27.0",
+        "duration": "28.0",
         "name": "rendering.mobile/canvas_40000_pixels_per_second"
     },
     {
-        "duration": "27.0",
+        "duration": "28.0",
         "name": "rendering.mobile/canvas_60000_pixels_per_second"
     },
     {
-        "duration": "36.0",
+        "duration": "35.0",
         "name": "rendering.mobile/canvas_75000_pixels_per_second"
     },
     {
@@ -248,7 +248,7 @@
         "name": "rendering.mobile/canvas_90000_pixels_per_second"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "rendering.mobile/canvas_animation_no_clear"
     },
     {
@@ -260,7 +260,7 @@
         "name": "rendering.mobile/canvas_font_cycler"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "rendering.mobile/canvas_lines"
     },
     {
@@ -276,19 +276,19 @@
         "name": "rendering.mobile/capitolvolkswagen_mobile_2018"
     },
     {
-        "duration": "12.0",
+        "duration": "13.0",
         "name": "rendering.mobile/card_expansion"
     },
     {
-        "duration": "13.0",
+        "duration": "14.0",
         "name": "rendering.mobile/card_expansion_animated"
     },
     {
-        "duration": "13.0",
+        "duration": "14.0",
         "name": "rendering.mobile/card_expansion_images_text"
     },
     {
-        "duration": "12.0",
+        "duration": "13.0",
         "name": "rendering.mobile/card_flying"
     },
     {
@@ -296,7 +296,7 @@
         "name": "rendering.mobile/cc_poster_circle"
     },
     {
-        "duration": "19.0",
+        "duration": "20.0",
         "name": "rendering.mobile/cc_scroll_text_only"
     },
     {
@@ -304,7 +304,7 @@
         "name": "rendering.mobile/chip_tune"
     },
     {
-        "duration": "42.0",
+        "duration": "44.0",
         "name": "rendering.mobile/cnn_2018"
     },
     {
@@ -312,7 +312,7 @@
         "name": "rendering.mobile/cnn_article_mobile_2018"
     },
     {
-        "duration": "42.0",
+        "duration": "43.0",
         "name": "rendering.mobile/cnn_mobile_2018"
     },
     {
@@ -328,11 +328,11 @@
         "name": "rendering.mobile/compositor_heavy_animation"
     },
     {
-        "duration": "14.0",
+        "duration": "15.0",
         "name": "rendering.mobile/coordinated_animation"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "rendering.mobile/crafty_mind"
     },
     {
@@ -396,7 +396,7 @@
         "name": "rendering.mobile/css_opacity_plus_n_layers_0"
     },
     {
-        "duration": "24.0",
+        "duration": "25.0",
         "name": "rendering.mobile/css_opacity_plus_n_layers_75"
     },
     {
@@ -500,7 +500,7 @@
         "name": "rendering.mobile/docs_paper.html"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "rendering.mobile/docs_resume.html"
     },
     {
@@ -508,7 +508,7 @@
         "name": "rendering.mobile/docs_table.html"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "rendering.mobile/draw_image"
     },
     {
@@ -516,11 +516,11 @@
         "name": "rendering.mobile/draw_image_not_pixel_aligned"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "rendering.mobile/dynamic_canvas_to_hw_accelerated_canvas.html"
     },
     {
-        "duration": "27.0",
+        "duration": "28.0",
         "name": "rendering.mobile/dynamic_cube_map"
     },
     {
@@ -544,11 +544,11 @@
         "name": "rendering.mobile/ebay_mobile_pinch_2018"
     },
     {
-        "duration": "31.0",
+        "duration": "30.0",
         "name": "rendering.mobile/ebay_scroll_2018"
     },
     {
-        "duration": "25.0",
+        "duration": "26.0",
         "name": "rendering.mobile/effect_games"
     },
     {
@@ -584,19 +584,19 @@
         "name": "rendering.mobile/falling_particle_simulation_gpu.html"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/famo_us_twitter_demo"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "rendering.mobile/fill_clear_rect.html"
     },
     {
-        "duration": "24.0",
+        "duration": "23.0",
         "name": "rendering.mobile/fill_shapes"
     },
     {
-        "duration": "22.0",
+        "duration": "21.0",
         "name": "rendering.mobile/filter_terrain_svg"
     },
     {
@@ -604,7 +604,7 @@
         "name": "rendering.mobile/flickr_scroll_2018"
     },
     {
-        "duration": "14.0",
+        "duration": "15.0",
         "name": "rendering.mobile/font_wipe"
     },
     {
@@ -612,95 +612,95 @@
         "name": "rendering.mobile/forecast.io_mobile_2018"
     },
     {
-        "duration": "23.0",
+        "duration": "22.0",
         "name": "rendering.mobile/get_image_data_cpu.html"
     },
     {
-        "duration": "23.0",
+        "duration": "22.0",
         "name": "rendering.mobile/get_image_data_gpu.html"
     },
     {
-        "duration": "10.0",
+        "duration": "9.0",
         "name": "rendering.mobile/gmail_2018"
     },
     {
-        "duration": "10.0",
+        "duration": "9.0",
         "name": "rendering.mobile/google_calendar_2018"
     },
     {
-        "duration": "10.0",
+        "duration": "9.0",
         "name": "rendering.mobile/google_docs_2018"
     },
     {
-        "duration": "20.0",
+        "duration": "19.0",
         "name": "rendering.mobile/google_image_search_2018"
     },
     {
-        "duration": "20.0",
+        "duration": "19.0",
         "name": "rendering.mobile/google_image_search_mobile_2018"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/google_news_ios"
     },
     {
-        "duration": "23.0",
+        "duration": "22.0",
         "name": "rendering.mobile/google_news_mobile_2018"
     },
     {
-        "duration": "10.0",
+        "duration": "9.0",
         "name": "rendering.mobile/google_plus_2018"
     },
     {
-        "duration": "15.0",
+        "duration": "14.0",
         "name": "rendering.mobile/google_plus_mobile_2018"
     },
     {
-        "duration": "10.0",
+        "duration": "9.0",
         "name": "rendering.mobile/google_search_mobile_pinch_2018"
     },
     {
-        "duration": "10.0",
+        "duration": "9.0",
         "name": "rendering.mobile/google_web_search_2018"
     },
     {
-        "duration": "18.0",
+        "duration": "17.0",
         "name": "rendering.mobile/google_web_search_mobile_2018"
     },
     {
-        "duration": "30.0",
+        "duration": "28.0",
         "name": "rendering.mobile/gpu_bound_shader.html"
     },
     {
-        "duration": "30.0",
+        "duration": "29.0",
         "name": "rendering.mobile/gsp.ro_mobile_2018"
     },
     {
-        "duration": "19.0",
+        "duration": "18.0",
         "name": "rendering.mobile/guardian_pathological_2018"
     },
     {
-        "duration": "24.0",
+        "duration": "22.0",
         "name": "rendering.mobile/guimark_vector_chart"
     },
     {
-        "duration": "10.0",
+        "duration": "9.0",
         "name": "rendering.mobile/gws_boogie_expansion"
     },
     {
-        "duration": "10.0",
+        "duration": "9.0",
         "name": "rendering.mobile/gws_google_expansion"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/hakim"
     },
     {
-        "duration": "13.0",
+        "duration": "14.0",
         "name": "rendering.mobile/horizontal_vertical_expansion"
     },
     {
-        "duration": "23.0",
+        "duration": "22.0",
         "name": "rendering.mobile/hw_accelerated_canvas_to_sw_canvas.html"
     },
     {
@@ -716,15 +716,15 @@
         "name": "rendering.mobile/idle_power_css_animation"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/idle_power_request_animation_frame"
     },
     {
-        "duration": "12.0",
+        "duration": "11.0",
         "name": "rendering.mobile/idle_power_set_timeout_long"
     },
     {
-        "duration": "12.0",
+        "duration": "11.0",
         "name": "rendering.mobile/idle_power_set_timetout"
     },
     {
@@ -732,31 +732,31 @@
         "name": "rendering.mobile/ie_chalkboard"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/ie_pirate_mark"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/infinite_scroll_element_n_layers_0"
     },
     {
-        "duration": "26.0",
+        "duration": "24.0",
         "name": "rendering.mobile/infinite_scroll_element_n_layers_75"
     },
     {
-        "duration": "27.0",
+        "duration": "26.0",
         "name": "rendering.mobile/infinite_scroll_element_n_layers_99"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/infinite_scroll_root_fixed_n_layers_0"
     },
     {
-        "duration": "26.0",
+        "duration": "24.0",
         "name": "rendering.mobile/infinite_scroll_root_fixed_n_layers_75"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/infinite_scroll_root_fixed_n_layers_99"
     },
     {
@@ -772,7 +772,7 @@
         "name": "rendering.mobile/infinite_scroll_root_n_layers_99"
     },
     {
-        "duration": "17.0",
+        "duration": "18.0",
         "name": "rendering.mobile/infinite_scrolling"
     },
     {
@@ -860,7 +860,7 @@
         "name": "rendering.mobile/list_animation_simple"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/list_recycle_transform"
     },
     {
@@ -876,7 +876,7 @@
         "name": "rendering.mobile/main_0fps_impl_60fps_no_update_jank"
     },
     {
-        "duration": "18.0",
+        "duration": "17.0",
         "name": "rendering.mobile/main_0fps_with_jank_impl_0fps"
     },
     {
@@ -940,11 +940,11 @@
         "name": "rendering.mobile/many_planets_deep"
     },
     {
-        "duration": "24.0",
+        "duration": "23.0",
         "name": "rendering.mobile/maps_perf_test"
     },
     {
-        "duration": "13.0",
+        "duration": "14.0",
         "name": "rendering.mobile/mask_transition_animation"
     },
     {
@@ -1020,11 +1020,11 @@
         "name": "rendering.mobile/mix_blend_mode_animation_screen"
     },
     {
-        "duration": "51.0",
+        "duration": "50.0",
         "name": "rendering.mobile/mlb_mobile_2018"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/mobile_news_sandbox"
     },
     {
@@ -1156,39 +1156,39 @@
         "name": "rendering.mobile/motionmark_svg_bouncing_svg_images_50"
     },
     {
-        "duration": "23.0",
+        "duration": "22.0",
         "name": "rendering.mobile/new_tilings"
     },
     {
-        "duration": "16.0",
+        "duration": "17.0",
         "name": "rendering.mobile/no_op_raf"
     },
     {
-        "duration": "15.0",
+        "duration": "16.0",
         "name": "rendering.mobile/no_op_scroll"
     },
     {
-        "duration": "14.0",
+        "duration": "15.0",
         "name": "rendering.mobile/no_op_settimeout"
     },
     {
-        "duration": "15.0",
+        "duration": "16.0",
         "name": "rendering.mobile/no_op_touch_handler"
     },
     {
-        "duration": "18.0",
+        "duration": "19.0",
         "name": "rendering.mobile/no_update_compositor_animation_with_janky_main_animation"
     },
     {
-        "duration": "30.0",
+        "duration": "31.0",
         "name": "rendering.mobile/non_opaque_background_compositor_thread_scrolling_00050_pixels_per_second"
     },
     {
-        "duration": "30.0",
+        "duration": "31.0",
         "name": "rendering.mobile/non_opaque_background_main_thread_scrolling_00050_pixels_per_second"
     },
     {
-        "duration": "20.0",
+        "duration": "21.0",
         "name": "rendering.mobile/nvidia_vertex_buffer_object"
     },
     {
@@ -1204,63 +1204,63 @@
         "name": "rendering.mobile/nytimes_scroll_2018"
     },
     {
-        "duration": "17.0",
+        "duration": "18.0",
         "name": "rendering.mobile/off_screen_main_60fps"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/off_screen_main_60fps_jank"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/offscreen_animation_no_damage"
     },
     {
-        "duration": "18.0",
+        "duration": "19.0",
         "name": "rendering.mobile/overlay_background_color_css_transitions_page"
     },
     {
-        "duration": "18.0",
+        "duration": "19.0",
         "name": "rendering.mobile/paint_worklet"
     },
     {
-        "duration": "13.0",
+        "duration": "14.0",
         "name": "rendering.mobile/parallax_effect"
     },
     {
-        "duration": "21.0",
+        "duration": "22.0",
         "name": "rendering.mobile/particles"
     },
     {
-        "duration": "23.0",
+        "duration": "24.0",
         "name": "rendering.mobile/pbs_pathological_2018"
     },
     {
-        "duration": "11.0",
+        "duration": "12.0",
         "name": "rendering.mobile/physical_simulation"
     },
     {
-        "duration": "19.0",
+        "duration": "20.0",
         "name": "rendering.mobile/pinterest_2018"
     },
     {
-        "duration": "14.0",
+        "duration": "16.0",
         "name": "rendering.mobile/pinterest_mobile_2018"
     },
     {
-        "duration": "21.0",
+        "duration": "22.0",
         "name": "rendering.mobile/put_and_create_imagebitmap_from_imagedata"
     },
     {
-        "duration": "19.0",
+        "duration": "20.0",
         "name": "rendering.mobile/put_get_image_data"
     },
     {
-        "duration": "19.0",
+        "duration": "20.0",
         "name": "rendering.mobile/put_image_data.html"
     },
     {
-        "duration": "15.0",
+        "duration": "16.0",
         "name": "rendering.mobile/raf"
     },
     {
@@ -1268,23 +1268,23 @@
         "name": "rendering.mobile/raf_animation"
     },
     {
-        "duration": "15.0",
+        "duration": "16.0",
         "name": "rendering.mobile/raf_canvas"
     },
     {
-        "duration": "15.0",
+        "duration": "16.0",
         "name": "rendering.mobile/raf_touch_animation"
     },
     {
-        "duration": "26.0",
+        "duration": "27.0",
         "name": "rendering.mobile/recode_pathological_2018"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/reddit_mobile_2018"
     },
     {
-        "duration": "19.0",
+        "duration": "20.0",
         "name": "rendering.mobile/runway_2019"
     },
     {
@@ -1296,27 +1296,27 @@
         "name": "rendering.mobile/second_batch_js_heavy"
     },
     {
-        "duration": "16.0",
+        "duration": "15.0",
         "name": "rendering.mobile/second_batch_js_light"
     },
     {
-        "duration": "16.0",
+        "duration": "15.0",
         "name": "rendering.mobile/second_batch_js_medium"
     },
     {
-        "duration": "43.0",
+        "duration": "44.0",
         "name": "rendering.mobile/sfgate_mobile_2018"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/sheets_render.html"
     },
     {
-        "duration": "27.0",
+        "duration": "26.0",
         "name": "rendering.mobile/silk_finance"
     },
     {
-        "duration": "22.0",
+        "duration": "21.0",
         "name": "rendering.mobile/simple_text_page"
     },
     {
@@ -1336,11 +1336,11 @@
         "name": "rendering.mobile/small_texture_uploads"
     },
     {
-        "duration": "29.0",
+        "duration": "28.0",
         "name": "rendering.mobile/smash_cat"
     },
     {
-        "duration": "26.0",
+        "duration": "25.0",
         "name": "rendering.mobile/spielzeugz"
     },
     {
@@ -1352,23 +1352,23 @@
         "name": "rendering.mobile/static_webgl_to_hw_accelerated_canvas.html"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/sticky_using_webkit"
     },
     {
-        "duration": "26.0",
+        "duration": "25.0",
         "name": "rendering.mobile/stroke_shapes"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/svg_icon_raster"
     },
     {
-        "duration": "12.0",
+        "duration": "13.0",
         "name": "rendering.mobile/swipe_to_dismiss"
     },
     {
-        "duration": "21.0",
+        "duration": "20.0",
         "name": "rendering.mobile/sync_scroll_offset"
     },
     {
@@ -1388,11 +1388,11 @@
         "name": "rendering.mobile/text_10000_pixels_per_second"
     },
     {
-        "duration": "34.0",
+        "duration": "33.0",
         "name": "rendering.mobile/text_20000_pixels_per_second"
     },
     {
-        "duration": "33.0",
+        "duration": "32.0",
         "name": "rendering.mobile/text_40000_pixels_per_second"
     },
     {
@@ -1400,11 +1400,11 @@
         "name": "rendering.mobile/text_60000_pixels_per_second"
     },
     {
-        "duration": "33.0",
+        "duration": "32.0",
         "name": "rendering.mobile/text_75000_pixels_per_second"
     },
     {
-        "duration": "33.0",
+        "duration": "32.0",
         "name": "rendering.mobile/text_90000_pixels_per_second"
     },
     {
@@ -1416,7 +1416,7 @@
         "name": "rendering.mobile/text_constant_full_page_raster_10000_pixels_per_second"
     },
     {
-        "duration": "35.0",
+        "duration": "34.0",
         "name": "rendering.mobile/text_constant_full_page_raster_20000_pixels_per_second"
     },
     {
@@ -1424,27 +1424,27 @@
         "name": "rendering.mobile/text_constant_full_page_raster_40000_pixels_per_second"
     },
     {
-        "duration": "33.0",
+        "duration": "32.0",
         "name": "rendering.mobile/text_constant_full_page_raster_60000_pixels_per_second"
     },
     {
-        "duration": "33.0",
+        "duration": "32.0",
         "name": "rendering.mobile/text_constant_full_page_raster_75000_pixels_per_second"
     },
     {
-        "duration": "33.0",
+        "duration": "32.0",
         "name": "rendering.mobile/text_constant_full_page_raster_90000_pixels_per_second"
     },
     {
-        "duration": "31.0",
+        "duration": "30.0",
         "name": "rendering.mobile/text_fling_05000_pixels_per_second"
     },
     {
-        "duration": "30.0",
+        "duration": "29.0",
         "name": "rendering.mobile/text_fling_10000_pixels_per_second"
     },
     {
-        "duration": "31.0",
+        "duration": "30.0",
         "name": "rendering.mobile/text_fling_20000_pixels_per_second"
     },
     {
@@ -1476,23 +1476,23 @@
         "name": "rendering.mobile/text_hover_90000_pixels_per_second"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/text_scrollbar_100_pixels_per_second"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/text_scrollbar_1200_pixels_per_second"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/text_scrollbar_200_pixels_per_second"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/text_scrollbar_2300_pixels_per_second"
     },
     {
-        "duration": "5.0",
+        "duration": "6.0",
         "name": "rendering.mobile/text_scrollbar_700_pixels_per_second"
     },
     {
@@ -1516,7 +1516,7 @@
         "name": "rendering.mobile/throughput_scrolling_passive_handler"
     },
     {
-        "duration": "30.0",
+        "duration": "29.0",
         "name": "rendering.mobile/throughput_scrolling_uncomposited"
     },
     {
@@ -1536,39 +1536,39 @@
         "name": "rendering.mobile/toBlob_small_canvas_in_worker.html"
     },
     {
-        "duration": "22.0",
+        "duration": "21.0",
         "name": "rendering.mobile/touch_handler_scrolling"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/transfer_from_imageBitmap.html"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/transform_transitions"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/transform_transitions_js_block"
     },
     {
-        "duration": "12.0",
+        "duration": "11.0",
         "name": "rendering.mobile/twitch_2018"
     },
     {
-        "duration": "12.0",
+        "duration": "11.0",
         "name": "rendering.mobile/twitch_mobile_pinch_2018"
     },
     {
-        "duration": "12.0",
+        "duration": "11.0",
         "name": "rendering.mobile/twitter_2018"
     },
     {
-        "duration": "24.0",
+        "duration": "23.0",
         "name": "rendering.mobile/twitter_mobile_2018"
     },
     {
-        "duration": "22.0",
+        "duration": "21.0",
         "name": "rendering.mobile/update_history_state"
     },
     {
@@ -1584,23 +1584,23 @@
         "name": "rendering.mobile/video_to_hw_accelerated_canvas"
     },
     {
-        "duration": "12.0",
+        "duration": "11.0",
         "name": "rendering.mobile/video_to_sub_texture"
     },
     {
-        "duration": "12.0",
+        "duration": "11.0",
         "name": "rendering.mobile/video_to_sub_texture_flip_and_premultiply"
     },
     {
-        "duration": "12.0",
+        "duration": "11.0",
         "name": "rendering.mobile/video_to_sub_texture_flip_y"
     },
     {
-        "duration": "12.0",
+        "duration": "11.0",
         "name": "rendering.mobile/video_to_sub_texture_premultiply"
     },
     {
-        "duration": "12.0",
+        "duration": "11.0",
         "name": "rendering.mobile/video_to_texture"
     },
     {
@@ -1608,27 +1608,27 @@
         "name": "rendering.mobile/web_animation_value_type_color"
     },
     {
-        "duration": "27.0",
+        "duration": "26.0",
         "name": "rendering.mobile/web_animation_value_type_length_3d"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/web_animation_value_type_length_complex"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/web_animation_value_type_length_simple"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/web_animation_value_type_path"
     },
     {
-        "duration": "25.0",
+        "duration": "24.0",
         "name": "rendering.mobile/web_animation_value_type_shadow"
     },
     {
-        "duration": "26.0",
+        "duration": "25.0",
         "name": "rendering.mobile/web_animation_value_type_transform_complex"
     },
     {
@@ -1648,7 +1648,7 @@
         "name": "rendering.mobile/web_animations_simultaneous"
     },
     {
-        "duration": "26.0",
+        "duration": "25.0",
         "name": "rendering.mobile/web_animations_staggered_chaining"
     },
     {
@@ -1680,7 +1680,7 @@
         "name": "rendering.mobile/wikipedia_delayed_scroll_start_2018"
     },
     {
-        "duration": "27.0",
+        "duration": "26.0",
         "name": "rendering.mobile/wikipedia_mobile_2018"
     },
     {
@@ -1700,7 +1700,7 @@
         "name": "rendering.mobile/wow_wiki_pathological_2018"
     },
     {
-        "duration": "59.0",
+        "duration": "58.0",
         "name": "rendering.mobile/wowwiki_mobile_2018"
     },
     {
@@ -1708,7 +1708,7 @@
         "name": "rendering.mobile/wsj_mobile_2018"
     },
     {
-        "duration": "32.0",
+        "duration": "31.0",
         "name": "rendering.mobile/yahoo_answers_2018"
     },
     {
@@ -1724,11 +1724,11 @@
         "name": "rendering.mobile/yahoo_news_mobile_2018"
     },
     {
-        "duration": "32.0",
+        "duration": "31.0",
         "name": "rendering.mobile/yahoo_sports_2018"
     },
     {
-        "duration": "31.0",
+        "duration": "30.0",
         "name": "rendering.mobile/yahoo_sports_pathological_2018"
     },
     {
@@ -1744,7 +1744,7 @@
         "name": "rendering.mobile/zdnet_pathological_2018"
     },
     {
-        "duration": "12.0",
+        "duration": "13.0",
         "name": "rendering.mobile/zoom_in_animation"
     },
     {
@@ -1764,7 +1764,7 @@
         "name": "system_health.memory_desktop/browse:news:flipboard:2020"
     },
     {
-        "duration": "64.0",
+        "duration": "62.0",
         "name": "system_health.memory_desktop/browse:news:hackernews:2020"
     },
     {
@@ -1856,7 +1856,7 @@
         "name": "system_health.memory_desktop/load:search:amazon:2018"
     },
     {
-        "duration": "23.0",
+        "duration": "22.0",
         "name": "system_health.memory_desktop/load:search:baidu:2018"
     },
     {
@@ -1864,7 +1864,7 @@
         "name": "system_health.memory_desktop/load:tools:chat:2020"
     },
     {
-        "duration": "37.0",
+        "duration": "38.0",
         "name": "system_health.memory_desktop/load:tools:docs:2019"
     },
     {
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index 5dda04f9..dcc3f675 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -403,9 +403,7 @@
   ]
 }
 
-android_library("ui_junit_test_support") {
-  # Skip platform checks since Robolectric depends on requires_android targets.
-  bypass_platform_checks = true
+robolectric_library("ui_junit_test_support") {
   testonly = true
   sources = [
     "junit/src/org/chromium/ui/shadows/ShadowAnimatedStateListDrawable.java",
diff --git a/ui/base/idle/idle_linux.cc b/ui/base/idle/idle_linux.cc
index 3d43db33..d1f3f058 100644
--- a/ui/base/idle/idle_linux.cc
+++ b/ui/base/idle/idle_linux.cc
@@ -45,11 +45,12 @@
     {"org.cinnamon.ScreenSaver", "/org/cinnamon/ScreenSaver",
      "org.cinnamon.ScreenSaver"},
     // gnome-screensaver
-    {"org.gnome.ScreenSaver", "/", "org.gnome.ScreenSaver"},
+    {"org.gnome.ScreenSaver", "/org/gnome/ScreenSaver",
+     "org.gnome.ScreenSaver"},
     // mate-screensaver
-    {"org.mate.ScreenSaver", "/", "org.mate.ScreenSaver"},
+    {"org.mate.ScreenSaver", "/org/mate/ScreenSaver", "org.mate.ScreenSaver"},
     // xfce4-screensaver
-    {"org.xfce.ScreenSaver", "/", "org.xfce.ScreenSaver"},
+    {"org.xfce.ScreenSaver", "/org/xfce/ScreenSaver", "org.xfce.ScreenSaver"},
 };
 
 constexpr size_t kServiceCount = sizeof(kServices) / sizeof(kServices[0]);
diff --git a/ui/base/ime/fuchsia/keyboard_client.cc b/ui/base/ime/fuchsia/keyboard_client.cc
index 4570ffd..c70f72ca 100644
--- a/ui/base/ime/fuchsia/keyboard_client.cc
+++ b/ui/base/ime/fuchsia/keyboard_client.cc
@@ -160,13 +160,12 @@
 
   // TODO(https://crbug.com/1187257): Use input3.KeyMeaning instead of US layout
   // as the default.
-  DomCode dom_code =
-      KeycodeConverter::UsbKeycodeToDomCode(static_cast<int>(key_event.key()));
+  DomCode dom_code = KeycodeConverter::UsbKeycodeToDomCode(key_event.key());
   DomKey dom_key;
   KeyboardCode key_code;
   if (!DomCodeToUsLayoutDomKey(dom_code, event_flags, &dom_key, &key_code)) {
     LOG(ERROR) << "DomCodeToUsLayoutDomKey() failed for key: "
-               << static_cast<uint32_t>(key_event.key());
+               << key_event.key();
   }
 
   return ui::KeyEvent(*event_type, key_code, dom_code, event_flags, dom_key,
diff --git a/ui/display/win/display_info.cc b/ui/display/win/display_info.cc
index 91bc087..6d392b7 100644
--- a/ui/display/win/display_info.cc
+++ b/ui/display/win/display_info.cc
@@ -17,7 +17,8 @@
     Display::Rotation rotation,
     int display_frequency,
     const gfx::Vector2dF& pixels_per_inch,
-    DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY output_technology)
+    DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY output_technology,
+    const std::string& label)
     : id_(DeviceIdFromDeviceName(monitor_info.szDevice)),
       screen_rect_(monitor_info.rcMonitor),
       screen_work_rect_(monitor_info.rcWork),
@@ -26,7 +27,21 @@
       rotation_(rotation),
       display_frequency_(display_frequency),
       pixels_per_inch_(pixels_per_inch),
-      output_technology_(output_technology) {}
+      output_technology_(output_technology),
+      label_(label) {}
+
+DisplayInfo::DisplayInfo(const DisplayInfo& other) {
+  id_ = other.id_;
+  screen_rect_ = other.screen_rect_;
+  screen_work_rect_ = other.screen_work_rect_;
+  device_scale_factor_ = other.device_scale_factor_;
+  sdr_white_level_ = other.sdr_white_level_;
+  rotation_ = other.rotation_;
+  display_frequency_ = other.display_frequency_;
+  pixels_per_inch_ = other.pixels_per_inch_;
+  output_technology_ = other.output_technology_;
+  label_ = other.label_;
+}
 
 DisplayInfo::~DisplayInfo() = default;
 
@@ -35,5 +50,16 @@
   return static_cast<int64_t>(base::Hash(base::WideToUTF8(device_name)));
 }
 
+bool DisplayInfo::operator==(const DisplayInfo& rhs) const {
+  return id_ == rhs.id_ && screen_rect_ == rhs.screen_rect_ &&
+         screen_work_rect_ == rhs.screen_work_rect_ &&
+         device_scale_factor_ == rhs.device_scale_factor_ &&
+         sdr_white_level_ == rhs.sdr_white_level_ &&
+         rotation_ == rhs.rotation_ &&
+         display_frequency_ == rhs.display_frequency_ &&
+         pixels_per_inch_ == rhs.pixels_per_inch_ &&
+         output_technology_ == rhs.output_technology_ && label_ == rhs.label_;
+}
+
 }  // namespace win
 }  // namespace display
diff --git a/ui/display/win/display_info.h b/ui/display/win/display_info.h
index f6c689b..1c1727d 100644
--- a/ui/display/win/display_info.h
+++ b/ui/display/win/display_info.h
@@ -23,7 +23,9 @@
               Display::Rotation rotation,
               int display_frequency,
               const gfx::Vector2dF& pixels_per_inch,
-              DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY output_technology);
+              DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY output_technology,
+              const std::string& label);
+  DisplayInfo(const DisplayInfo& other);
   ~DisplayInfo();
 
   static int64_t DeviceIdFromDeviceName(const wchar_t* device_name);
@@ -39,6 +41,10 @@
   DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY output_technology() const {
     return output_technology_;
   }
+  const std::string& label() const { return label_; }
+
+  bool operator==(const DisplayInfo& rhs) const;
+  bool operator!=(const DisplayInfo& rhs) const { return !(*this == rhs); }
 
  private:
   int64_t id_;
@@ -52,6 +58,7 @@
   // monitors. In non-touch cases, it will be set to Zero.
   gfx::Vector2dF pixels_per_inch_;
   DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY output_technology_;
+  std::string label_;
 };
 
 }  // namespace win
diff --git a/ui/display/win/scaling_util_unittest.cc b/ui/display/win/scaling_util_unittest.cc
index 79c1a04..d74b611 100644
--- a/ui/display/win/scaling_util_unittest.cc
+++ b/ui/display/win/scaling_util_unittest.cc
@@ -21,7 +21,8 @@
                                                  gfx::Rect(x, y, width, height),
                                                  kFakeDisplayName);
   return DisplayInfo(monitor_info, scale_factor, 1.0f, Display::ROTATE_0, 60,
-                     gfx::Vector2dF(), DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER);
+                     gfx::Vector2dF(), DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER,
+                     std::string());
 }
 
 ::testing::AssertionResult AssertOffsetsEqual(
diff --git a/ui/display/win/screen_win.cc b/ui/display/win/screen_win.cc
index fe2b3d7..65deacd6 100644
--- a/ui/display/win/screen_win.cc
+++ b/ui/display/win/screen_win.cc
@@ -129,6 +129,24 @@
   return absl::nullopt;
 }
 
+// Gets a user-friendly name for a given display using EDID data. Returns an
+// empty string if the provided path is unset/nullopt or EDID data is not
+// available for the device.
+std::string GetFriendlyDeviceName(
+    const absl::optional<DISPLAYCONFIG_PATH_INFO>& path) {
+  if (!path)
+    return std::string();
+  DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {};
+  targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
+  targetName.header.size = sizeof(targetName);
+  targetName.header.adapterId = path->targetInfo.adapterId;
+  targetName.header.id = path->targetInfo.id;
+  LONG result = DisplayConfigGetDeviceInfo(&targetName.header);
+  if (result == ERROR_SUCCESS && targetName.flags.friendlyNameFromEdid)
+    return base::WideToUTF8(targetName.monitorFriendlyDeviceName);
+  return std::string();
+}
+
 float GetSDRWhiteLevel(const absl::optional<DISPLAYCONFIG_PATH_INFO>& path) {
   if (path) {
     DISPLAYCONFIG_SDR_WHITE_LEVEL white_level = {};
@@ -289,6 +307,7 @@
       display_info.screen_work_rect(), 1.0f / scale_factor));
   display.set_rotation(display_info.rotation());
   display.set_display_frequency(display_info.display_frequency());
+  display.set_label(display_info.label());
 
   // DisplayColorSpaces is created using the forced color profile if present, or
   // from the ICC profile provided by |color_profile_reader| for SDR content,
@@ -477,7 +496,7 @@
   display_infos->emplace_back(
       monitor_info, GetMonitorScaleFactor(monitor), GetSDRWhiteLevel(path_info),
       display_settings.rotation, display_settings.frequency, pixels_per_inch,
-      GetOutputTechnology(path_info));
+      GetOutputTechnology(path_info), GetFriendlyDeviceName(path_info));
   return TRUE;
 }
 
diff --git a/ui/display/win/screen_win_display.cc b/ui/display/win/screen_win_display.cc
index 322c470e..5e272b5 100644
--- a/ui/display/win/screen_win_display.cc
+++ b/ui/display/win/screen_win_display.cc
@@ -20,6 +20,7 @@
                                                1.0f / scale_factor));
   display.set_rotation(display_info.rotation());
   display.set_display_frequency(display_info.display_frequency());
+  display.set_label(display_info.label());
   return display;
 }
 
diff --git a/ui/display/win/screen_win_unittest.cc b/ui/display/win/screen_win_unittest.cc
index ea12f4a..5a1210e9 100644
--- a/ui/display/win/screen_win_unittest.cc
+++ b/ui/display/win/screen_win_unittest.cc
@@ -165,9 +165,9 @@
     MONITORINFOEX monitor_info =
         win::test::CreateMonitorInfo(pixel_bounds, pixel_work, device_name);
     monitor_infos_.push_back(monitor_info);
-    display_infos_.push_back(DisplayInfo(monitor_info, device_scale_factor,
-                                         1.0f, Display::ROTATE_0, 60,
-                                         gfx::Vector2dF(), tech));
+    display_infos_.push_back(
+        DisplayInfo(monitor_info, device_scale_factor, 1.0f, Display::ROTATE_0,
+                    60, gfx::Vector2dF(), tech, std::string()));
   }
 
   HWND CreateFakeHwnd(const gfx::Rect& bounds) override {
diff --git a/ui/display/win/test/scoped_screen_win.cc b/ui/display/win/test/scoped_screen_win.cc
index edb39b8c..c76ab61 100644
--- a/ui/display/win/test/scoped_screen_win.cc
+++ b/ui/display/win/test/scoped_screen_win.cc
@@ -17,7 +17,8 @@
       CreateMonitorInfo(kPixelBounds, kPixelWork, L"primary");
   UpdateFromDisplayInfos(
       {{monitor_info, /*device_scale_factor=*/1.0f, 1.0f, Display::ROTATE_0, 60,
-        gfx::Vector2dF(96.0, 96.0), DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER}});
+        gfx::Vector2dF(96.0, 96.0), DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER,
+        std::string()}});
 }
 
 }  // namespace test
diff --git a/ui/events/keycodes/dom/keycode_converter.cc b/ui/events/keycodes/dom/keycode_converter.cc
index bdfb307..d0f8c2a 100644
--- a/ui/events/keycodes/dom/keycode_converter.cc
+++ b/ui/events/keycodes/dom/keycode_converter.cc
@@ -5,6 +5,7 @@
 #include "ui/events/keycodes/dom/keycode_converter.h"
 
 #include "base/logging.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversion_utils.h"
 #include "build/build_config.h"
 #include "ui/events/keycodes/dom/dom_code.h"
@@ -223,7 +224,7 @@
 #endif
 
 // static
-DomCode KeycodeConverter::CodeStringToDomCode(const std::string& code) {
+DomCode KeycodeConverter::CodeStringToDomCode(base::StringPiece code) {
   if (code.empty())
     return DomCode::NONE;
   for (auto& mapping : kDomCodeMappings) {
@@ -236,9 +237,29 @@
 }
 
 // static
-const char* KeycodeConverter::DomCodeToCodeString(DomCode dom_code) {
+std::string KeycodeConverter::DomCodeToCodeString(DomCode dom_code) {
+  const auto usb_keycode = static_cast<uint32_t>(dom_code);
+
+  // Generate some continuous runs of codes, rather than looking them up.
+  if (dom_code >= DomCode::US_A && dom_code <= DomCode::US_Z) {
+    const int index = usb_keycode - static_cast<uint32_t>(DomCode::US_A);
+    return base::StringPrintf("Key%c", 'A' + index);
+  } else if (dom_code >= DomCode::DIGIT1 && dom_code <= DomCode::DIGIT0) {
+    const int index = usb_keycode - static_cast<uint32_t>(DomCode::DIGIT1);
+    return base::StringPrintf("Digit%d", (index + 1) % 10);
+  } else if (dom_code >= DomCode::NUMPAD1 && dom_code <= DomCode::NUMPAD0) {
+    const int index = usb_keycode - static_cast<uint32_t>(DomCode::NUMPAD1);
+    return base::StringPrintf("Numpad%d", (index + 1) % 10);
+  } else if (dom_code >= DomCode::F1 && dom_code <= DomCode::F12) {
+    const int index = usb_keycode - static_cast<uint32_t>(DomCode::F1);
+    return base::StringPrintf("F%d", index + 1);
+  } else if (dom_code >= DomCode::F13 && dom_code <= DomCode::F24) {
+    const int index = usb_keycode - static_cast<uint32_t>(DomCode::F13);
+    return base::StringPrintf("F%d", index + 13);
+  }
+
   for (auto& mapping : kDomCodeMappings) {
-    if (mapping.usb_keycode == static_cast<uint32_t>(dom_code)) {
+    if (mapping.usb_keycode == usb_keycode) {
       if (mapping.code)
         return mapping.code;
       break;
@@ -297,7 +318,7 @@
 }
 
 // static
-DomKey KeycodeConverter::KeyStringToDomKey(const std::string& key) {
+DomKey KeycodeConverter::KeyStringToDomKey(base::StringPiece key) {
   if (key.empty())
     return DomKey::NONE;
   // Check for standard key names.
@@ -315,12 +336,12 @@
   }
   // Otherwise, if the string contains a single Unicode character,
   // the key value is that character.
+  const auto key_length = static_cast<int32_t>(key.length());
   int32_t char_index = 0;
   base_icu::UChar32 character;
-  if (base::ReadUnicodeCharacter(key.c_str(),
-                                 static_cast<int32_t>(key.length()),
-                                 &char_index, &character) &&
-      key[++char_index] == 0) {
+  if (base::ReadUnicodeCharacter(key.data(), key_length, &char_index,
+                                 &character) &&
+      ++char_index == key_length) {
     return DomKey::FromCharacter(character);
   }
   return DomKey::NONE;
@@ -439,22 +460,4 @@
   return InvalidUsbKeycode();
 }
 
-// static
-uint32_t KeycodeConverter::CodeStringToUsbKeycode(const std::string& code) {
-  if (code.empty())
-    return InvalidUsbKeycode();
-
-  for (auto& mapping : kDomCodeMappings) {
-    if (mapping.code && code == mapping.code) {
-      return mapping.usb_keycode;
-    }
-  }
-  return InvalidUsbKeycode();
-}
-
-// static
-int KeycodeConverter::CodeStringToNativeKeycode(const std::string& code) {
-  return UsbKeycodeToNativeKeycode(CodeStringToUsbKeycode(code));
-}
-
 }  // namespace ui
diff --git a/ui/events/keycodes/dom/keycode_converter.h b/ui/events/keycodes/dom/keycode_converter.h
index d06621c..ee5ff4b 100644
--- a/ui/events/keycodes/dom/keycode_converter.h
+++ b/ui/events/keycodes/dom/keycode_converter.h
@@ -9,6 +9,7 @@
 #include <stdint.h>
 #include <string>
 
+#include "base/strings/string_piece.h"
 #include "build/build_config.h"
 #include "ui/events/keycodes/dom/dom_key.h"
 
@@ -91,11 +92,11 @@
   static KeyboardCode MapPositionalDomCodeToUSShortcutKey(DomCode code);
 #endif
 
-  // Convert a UI Events |code| string value into a DomCode.
-  static DomCode CodeStringToDomCode(const std::string& code);
-
-  // Convert a DomCode into a UI Events |code| string value.
-  static const char* DomCodeToCodeString(DomCode dom_code);
+  // Conversion between DOM Code string and DomCode enum values.
+  // Returns the invalid value if the supplied code is not recognized,
+  // or has no mapping.
+  static DomCode CodeStringToDomCode(base::StringPiece code);
+  static std::string DomCodeToCodeString(DomCode dom_code);
 
   // Return the DomKeyLocation of a DomCode. The DomKeyLocation distinguishes
   // keys with the same meaning, and therefore the same DomKey or non-located
@@ -108,10 +109,10 @@
   // - a key name from http://www.w3.org/TR/DOM-Level-3-Events-key/, or
   // - a single Unicode character (represented in UTF-8).
   // Returns DomKey::NONE for other inputs, including |nullptr|.
-  static DomKey KeyStringToDomKey(const std::string& key);
+  static DomKey KeyStringToDomKey(base::StringPiece key);
 
   // Convert a DomKey into a UI Events |key| string value.
-  // For an invalid DomKey, returns an empty string.
+  // Returns an empty string for invalid DomKey values.
   static std::string DomKeyToKeyString(DomKey dom_key);
 
   // Returns true if the DomKey is a modifier.
@@ -128,24 +129,18 @@
   // Return the value that identifies an invalid USB keycode.
   static uint32_t InvalidUsbKeycode();
 
-  // Convert a USB keycode into an equivalent platform native keycode.
+  // Conversion between USB keycode and native keycode values.
+  // Returns the invalid value if the supplied code is not recognized,
+  // or has no mapping.
   static int UsbKeycodeToNativeKeycode(uint32_t usb_keycode);
-
-  // Convert a platform native keycode into an equivalent USB keycode.
   static uint32_t NativeKeycodeToUsbKeycode(int native_keycode);
 
-  // Convert a USB keycode into a DomCode.
+  // Conversion between USB keycode and DomCode values.
+  // Returns the "invalid" value if the supplied key code is not
+  // recognized.
   static DomCode UsbKeycodeToDomCode(uint32_t usb_keycode);
-
-  // Convert a DomCode into a USB keycode.
   static uint32_t DomCodeToUsbKeycode(DomCode dom_code);
 
-  // Convert a UI Event |code| string into a USB keycode value.
-  static uint32_t CodeStringToUsbKeycode(const std::string& code);
-
-  // Convert a UI Event |code| string into a native keycode.
-  static int CodeStringToNativeKeycode(const std::string& code);
-
   // Static methods to support testing.
   static size_t NumKeycodeMapEntriesForTest();
   static const KeycodeMapEntry* GetKeycodeMapForTest();
diff --git a/ui/events/keycodes/dom/keycode_converter_unittest.cc b/ui/events/keycodes/dom/keycode_converter_unittest.cc
index 3cbe92c0..0d72bd39 100644
--- a/ui/events/keycodes/dom/keycode_converter_unittest.cc
+++ b/ui/events/keycodes/dom/keycode_converter_unittest.cc
@@ -169,7 +169,7 @@
     if (entry->code) {
       ui::DomCode code = ui::KeycodeConverter::CodeStringToDomCode(entry->code);
       EXPECT_STREQ(entry->code,
-                   ui::KeycodeConverter::DomCodeToCodeString(code));
+                   ui::KeycodeConverter::DomCodeToCodeString(code).c_str());
     }
     ui::DomCode code =
         ui::KeycodeConverter::NativeKeycodeToDomCode(entry->native_keycode);
diff --git a/ui/events/keycodes/keyboard_code_conversion_unittest.cc b/ui/events/keycodes/keyboard_code_conversion_unittest.cc
index 90bc05d5..5fe65a1 100644
--- a/ui/events/keycodes/keyboard_code_conversion_unittest.cc
+++ b/ui/events/keycodes/keyboard_code_conversion_unittest.cc
@@ -36,10 +36,10 @@
   ui::DomKey result_dom_key = ui::DomKey::NONE;
   ui::KeyboardCode result_key_code = ui::VKEY_UNKNOWN;
   bool success = f(dom_code, event_flags, &result_dom_key, &result_key_code);
-  SCOPED_TRACE(
-      base::StringPrintf("%s %s %06X:%04X", label,
-                         ui::KeycodeConverter::DomCodeToCodeString(dom_code),
-                         static_cast<int>(dom_code), event_flags));
+  SCOPED_TRACE(base::StringPrintf(
+      "%s %s %06X:%04X", label,
+      ui::KeycodeConverter::DomCodeToCodeString(dom_code).c_str(),
+      static_cast<int>(dom_code), event_flags));
   EXPECT_EQ(result.defined, success);
   if (success) {
     EXPECT_EQ(result.dom_key, result_dom_key)
diff --git a/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc b/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc
index cc0c54f..d52acd96 100644
--- a/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc
+++ b/ui/events/ozone/layout/keyboard_layout_engine_unittest.cc
@@ -201,7 +201,7 @@
     KeyboardCode keycode;
     SCOPED_TRACE(base::StringPrintf(
         "%s(%s, 0x%X)", name,
-        KeycodeConverter::DomCodeToCodeString(t.input_dom_code),
+        KeycodeConverter::DomCodeToCodeString(t.input_dom_code).c_str(),
         t.input_flags));
     EXPECT_TRUE(
         engine->Lookup(t.input_dom_code, t.input_flags, &dom_key, &keycode));
diff --git a/ui/gfx/color_conversion_sk_filter_cache.cc b/ui/gfx/color_conversion_sk_filter_cache.cc
index 77d8acf..56b035c 100644
--- a/ui/gfx/color_conversion_sk_filter_cache.cc
+++ b/ui/gfx/color_conversion_sk_filter_cache.cc
@@ -21,9 +21,6 @@
 
 namespace {
 
-const base::Feature kToneMappingV2{"ToneMappingV2",
-                                   base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Additional YUV information to skia renderer to draw 9- and 10- bits color.
 struct YUVInput {
   float offset = 0.f;
@@ -89,14 +86,7 @@
 
   if (!effect) {
     gfx::ColorTransform::Options options;
-
-    static const bool tone_mapping_v2_enabled =
-        base::FeatureList::IsEnabled(kToneMappingV2);
-    if (tone_mapping_v2_enabled)
-      options.tone_map_pq_and_hlg_to_dst = true;
-    else
-      options.tone_map_pq_and_hlg_to_sdr = dst_max_luminance_relative == 1.f;
-
+    options.tone_map_pq_and_hlg_to_dst = true;
     options.sdr_max_luminance_nits = key.sdr_max_luminance_nits;
     // TODO(https://crbug.com/1286076): Ensure that, when tone mapping using
     // `dst_max_luminance_relative` is implemented, the gfx::ColorTransform's
diff --git a/ui/gfx/color_transform.cc b/ui/gfx/color_transform.cc
index c7f9d753..4fda03bc 100644
--- a/ui/gfx/color_transform.cc
+++ b/ui/gfx/color_transform.cc
@@ -917,135 +917,6 @@
   }
 };
 
-class ColorTransformPQToneMapToLinear : public ColorTransformStep {
- public:
-  static float ToLinearToneMap(float v) {
-    v = max(0.0f, v);
-    return min(2.3f * pow(v, 2.8f), v / 5.0f + 0.8f);
-  }
-
-  static float ToLinearPQ(float v) {
-    v = max(0.0f, v);
-    float m1 = (2610.0f / 4096.0f) / 4.0f;
-    float m2 = (2523.0f / 4096.0f) * 128.0f;
-    float c1 = 3424.0f / 4096.0f;
-    float c2 = (2413.0f / 4096.0f) * 32.0f;
-    float c3 = (2392.0f / 4096.0f) * 32.0f;
-    float p = pow(v, 1.0f / m2);
-    v = powf(max(p - c1, 0.0f) / (c2 - c3 * p), 1.0f / m1);
-    v *= 10000.0f / ColorSpace::kDefaultSDRWhiteLevel;
-    return v;
-  }
-
-  // Assumes BT2020 primaries.
-  static float Luma(const ColorTransform::TriStim& c) {
-    return c.x() * 0.2627f + c.y() * 0.6780f + c.z() * 0.0593f;
-  }
-
-  static ColorTransform::TriStim ClipToWhite(ColorTransform::TriStim* c) {
-    float maximum = max(max(c->x(), c->y()), c->z());
-    if (maximum > 1.0f) {
-      float l = Luma(*c);
-      c->Scale(1.0f / maximum);
-      ColorTransform::TriStim white(1.0f, 1.0f, 1.0f);
-      white.Scale((1.0f - 1.0f / maximum) * l / Luma(white));
-      ColorTransform::TriStim black(0.0f, 0.0f, 0.0f);
-      *c += white - black;
-    }
-    return *c;
-  }
-
-  void Transform(ColorTransform::TriStim* colors, size_t num) const override {
-    for (size_t i = 0; i < num; i++) {
-      ColorTransform::TriStim ret(ToLinearToneMap(colors[i].x()),
-                                  ToLinearToneMap(colors[i].y()),
-                                  ToLinearToneMap(colors[i].z()));
-      if (Luma(ret) > 0.0) {
-        ColorTransform::TriStim smpte2084(ToLinearPQ(colors[i].x()),
-                                          ToLinearPQ(colors[i].y()),
-                                          ToLinearPQ(colors[i].z()));
-        smpte2084.Scale(Luma(ret) / Luma(smpte2084));
-        ret = ClipToWhite(&smpte2084);
-      }
-      colors[i] = ret;
-    }
-  }
-
-  void AppendShaderSource(std::stringstream* hdr,
-                          std::stringstream* src,
-                          size_t step_index) const override {
-    auto sdr_white_level =
-        base::NumberToString(ColorSpace::kDefaultSDRWhiteLevel);
-    *hdr << "vec3 PQToneMapStep" << step_index << "(vec3 color) {\n"
-         << "  vec3 result = max(color, 0.0);\n"
-         << "  result =\n"
-         << "      min(2.3 * pow(result, vec3(2.8)), result / 5.0 + 0.8);\n"
-         << "  vec3 luma_vec = vec3(0.2627, 0.6780, 0.0593);\n"
-         << "  float luma = dot(result, luma_vec);\n"
-         << "  if (luma > 0.0) {\n"
-         << "    result = max(color, 0.0);\n"
-         << "    float m1 = (2610.0 / 4096.0) / 4.0;\n"
-         << "    float m2 = (2523.0 / 4096.0) * 128.0;\n"
-         << "    float c1 = 3424.0 / 4096.0;\n"
-         << "    float c2 = (2413.0 / 4096.0) * 32.0;\n"
-         << "    float c3 = (2392.0 / 4096.0) * 32.0;\n"
-         << "    vec3 p = pow(max(result, 0.0), vec3(1.0 / m2));\n"
-         << "    result =\n"
-         << "        pow(max(p - c1, 0.0) / (c2 - c3 * p), vec3(1.0 / m1));\n"
-         << "    result *= 10000.0 / " + sdr_white_level + ".0;\n"
-         << "    result *= luma / dot(result, luma_vec);\n"
-         << "    float c_max = max(max(result.x, result.y), result.z);\n"
-         << "    if (c_max > 1.0) {\n"
-         << "      luma = dot(result, luma_vec);\n"
-         << "      float s = 1.0 / c_max;\n"
-         << "      result *= s;\n"
-         << "      vec3 white = vec3(1.0);\n"
-         << "      white *= (1.0 - s) * luma / dot(white, luma_vec);\n"
-         << "      result += white - vec3(0.0);\n"
-         << "    }\n"
-         << "  }\n"
-         << "  return result;\n"
-         << "}\n";
-    *src << "  color.rgb = PQToneMapStep" << step_index << "(color.rgb);\n";
-  }
-
-  void AppendSkShaderSource(std::stringstream* src) const override {
-    auto sdr_white_level =
-        base::NumberToString(ColorSpace::kDefaultSDRWhiteLevel);
-    *src << "{\n"
-         << "  half4 result = max(color, 0.0);\n"
-         << "  result =\n"
-         << "      min(2.3 * pow(result, half4(2.8)), result / 5.0 + 0.8);\n"
-         << "  half4 luma_vec = half4(0.2627, 0.6780, 0.0593, 0.0);\n"
-         << "  half luma = dot(result, luma_vec);\n"
-         << "  if (luma > 0.0) {\n"
-         << "    result = max(color, 0.0);\n"
-         << "    half m1 = (2610.0 / 4096.0) / 4.0;\n"
-         << "    half m2 = (2523.0 / 4096.0) * 128.0;\n"
-         << "    half c1 = 3424.0 / 4096.0;\n"
-         << "    half c2 = (2413.0 / 4096.0) * 32.0;\n"
-         << "    half c3 = (2392.0 / 4096.0) * 32.0;\n"
-         << "    half4 p = pow(max(result, 0.0), half4(1.0 / m2));\n"
-         << "    result =\n"
-         << "        pow(max(p - c1, 0.0) / (c2 - c3 * p), half4(1.0 / m1));\n"
-         << "    result *= 10000.0 / " + sdr_white_level + ".0;\n"
-         << "    result *= luma / dot(result, luma_vec);\n"
-         << "    half c_max = max(max(result.x, result.y), result.z);\n"
-         << "    if (c_max > 1.0) {\n"
-         << "      luma = dot(result, luma_vec);\n"
-         << "      half s = 1.0 / c_max;\n"
-         << "      result *= s;\n"
-         << "      half4 white = half4(1.0);\n"
-         << "      white *= (1.0 - s) * luma / dot(white, luma_vec);\n"
-         << "      result += white - half4(0.0);\n"
-         << "    }\n"
-         << "  }\n"
-         << "  result.a = color.a;\n"
-         << "  color = result;\n"
-         << "}\n";
-  }
-};
-
 // Apply the HLG OOTF for a specified maximum luminance.
 class ColorTransformHLGOOTF : public ColorTransformStep {
  public:
@@ -1188,13 +1059,7 @@
 
   switch (src.GetTransferID()) {
     case ColorSpace::TransferID::HLG:
-      if (options.tone_map_pq_and_hlg_to_sdr) {
-        // HLG is designed such that treating it as 2.2 gamma content works
-        // well.
-        constexpr skcms_TransferFunction kGamma22 = {2.2, 1, 0, 0, 0, 0, 0};
-        steps_.push_back(std::make_unique<ColorTransformSkTransferFn>(
-            kGamma22, src.HasExtendedSkTransferFn()));
-      } else if (options.tone_map_pq_and_hlg_to_dst) {
+      if (options.tone_map_pq_and_hlg_to_dst) {
         // Convert to linear with a maximum value of 1.
         steps_.push_back(std::make_unique<ColorTransformHLGToLinear>(
             12.f * ColorSpace::kDefaultSDRWhiteLevel));
@@ -1204,12 +1069,8 @@
       }
       break;
     case ColorSpace::TransferID::PQ:
-      if (options.tone_map_pq_and_hlg_to_sdr) {
-        steps_.push_back(std::make_unique<ColorTransformPQToneMapToLinear>());
-      } else {
-        steps_.push_back(std::make_unique<ColorTransformPQToLinear>(
-            options.sdr_max_luminance_nits));
-      }
+      steps_.push_back(std::make_unique<ColorTransformPQToLinear>(
+          options.sdr_max_luminance_nits));
       break;
     case ColorSpace::TransferID::PIECEWISE_HDR: {
       skcms_TransferFunction fn;
diff --git a/ui/gfx/color_transform.h b/ui/gfx/color_transform.h
index 11a56bca..d3f6e5d 100644
--- a/ui/gfx/color_transform.h
+++ b/ui/gfx/color_transform.h
@@ -24,10 +24,6 @@
     uint32_t src_bit_depth = kDefaultBitDepth;
     uint32_t dst_bit_depth = kDefaultBitDepth;
 
-    // If set to true, then PQ and HLG inputs are tone mapped to fit into
-    // the SDR range.
-    bool tone_map_pq_and_hlg_to_sdr = false;
-
     // If set to true, then map PQ and HLG imputs such that their maximum
     // luminance will be `dst_max_luminance_relative`.
     bool tone_map_pq_and_hlg_to_dst = false;
diff --git a/ui/gfx/color_transform_unittest.cc b/ui/gfx/color_transform_unittest.cc
index b9272c6..7d77fba 100644
--- a/ui/gfx/color_transform_unittest.cc
+++ b/ui/gfx/color_transform_unittest.cc
@@ -901,60 +901,4 @@
   }
 }
 
-TEST(ColorSpaceTest, HLGHDRToSDR) {
-  ColorSpace hlg_cs(ColorSpace::PrimaryID::BT709, ColorSpace::TransferID::HLG);
-  ColorSpace dest_sdr_cs(ColorSpace::PrimaryID::BT709,
-                         ColorSpace::TransferID::LINEAR);
-  gfx::ColorTransform::Options sdr_options;
-  sdr_options.tone_map_pq_and_hlg_to_sdr = true;
-  auto sdr_transform =
-      ColorTransform::NewColorTransform(hlg_cs, dest_sdr_cs, sdr_options);
-
-  // HLG conversion will produce values above 1 w/o intervention.
-  ColorTransform::TriStim sdr_val = {1, 1, 1};
-  sdr_transform->Transform(&sdr_val, 1);
-  EXPECT_FLOAT_EQ(sdr_val.x(), 1);
-  EXPECT_FLOAT_EQ(sdr_val.y(), 1);
-  EXPECT_FLOAT_EQ(sdr_val.z(), 1);
-
-  ColorSpace dest_hdr_cs(ColorSpace::PrimaryID::BT709,
-                         ColorSpace::TransferID::LINEAR_HDR);
-  gfx::ColorTransform::Options hdr_options;
-  hdr_options.tone_map_pq_and_hlg_to_sdr = false;
-  auto hdr_transform =
-      ColorTransform::NewColorTransform(hlg_cs, dest_hdr_cs, hdr_options);
-
-  ColorTransform::TriStim hdr_val = {1, 1, 1};
-  hdr_transform->Transform(&hdr_val, 1);
-  EXPECT_NE(sdr_val, hdr_val);
-}
-
-TEST(ColorSpaceTest, PQHDRToSDR) {
-  ColorSpace pq_cs(ColorSpace::PrimaryID::BT709, ColorSpace::TransferID::PQ);
-  ColorSpace dest_sdr_cs(ColorSpace::PrimaryID::BT709,
-                         ColorSpace::TransferID::LINEAR);
-  gfx::ColorTransform::Options sdr_options;
-  sdr_options.tone_map_pq_and_hlg_to_sdr = true;
-  auto sdr_transform =
-      ColorTransform::NewColorTransform(pq_cs, dest_sdr_cs, sdr_options);
-
-  // PQ conversion will produce values above 1 w/o intervention.
-  ColorTransform::TriStim sdr_val = {1, 1, 1};
-  sdr_transform->Transform(&sdr_val, 1);
-  EXPECT_FLOAT_EQ(sdr_val.x(), 1);
-  EXPECT_FLOAT_EQ(sdr_val.y(), 1);
-  EXPECT_FLOAT_EQ(sdr_val.z(), 1);
-
-  ColorSpace dest_hdr_cs(ColorSpace::PrimaryID::BT709,
-                         ColorSpace::TransferID::LINEAR_HDR);
-  gfx::ColorTransform::Options hdr_options;
-  hdr_options.tone_map_pq_and_hlg_to_sdr = false;
-  auto hdr_transform =
-      ColorTransform::NewColorTransform(pq_cs, dest_hdr_cs, hdr_options);
-
-  ColorTransform::TriStim hdr_val = {1, 1, 1};
-  hdr_transform->Transform(&hdr_val, 1);
-  EXPECT_NE(sdr_val, hdr_val);
-}
-
 }  // namespace gfx
diff --git a/ui/webui/resources/cr_components/most_visited/most_visited.ts b/ui/webui/resources/cr_components/most_visited/most_visited.ts
index f10b010..b2c5b63 100644
--- a/ui/webui/resources/cr_components/most_visited/most_visited.ts
+++ b/ui/webui/resources/cr_components/most_visited/most_visited.ts
@@ -548,9 +548,9 @@
   private getFaviconUrl_(url: Url): string {
     const faviconUrl = new URL('chrome://favicon2/');
     faviconUrl.searchParams.set('size', '24');
-    faviconUrl.searchParams.set('scale_factor', '1x');
-    faviconUrl.searchParams.set('show_fallback_monogram', '');
-    faviconUrl.searchParams.set('page_url', url.url);
+    faviconUrl.searchParams.set('scaleFactor', '1x');
+    faviconUrl.searchParams.set('showFallbackMonogram', '');
+    faviconUrl.searchParams.set('pageUrl', url.url);
     return faviconUrl.href;
   }
 
diff --git a/ui/webui/resources/js/icon.js b/ui/webui/resources/js/icon.js
index 8888fc0b..2d3d1e07 100644
--- a/ui/webui/resources/js/icon.js
+++ b/ui/webui/resources/js/icon.js
@@ -107,7 +107,7 @@
 function getBaseFaviconUrl() {
   const faviconUrl = new URL('chrome://favicon2/');
   faviconUrl.searchParams.set('size', '16');
-  faviconUrl.searchParams.set('scale_factor', 'SCALEFACTORx');
+  faviconUrl.searchParams.set('scaleFactor', 'SCALEFACTORx');
   return faviconUrl;
 }
 
@@ -119,7 +119,7 @@
  */
 export function getFavicon(url) {
   const faviconUrl = getBaseFaviconUrl();
-  faviconUrl.searchParams.set('icon_url', url);
+  faviconUrl.searchParams.set('iconUrl', url);
   return getImageSet(faviconUrl.toString());
 }
 
@@ -142,13 +142,13 @@
   // chrome://favicon2 format in components/favicon_base/favicon_url_parser.h.
   const faviconUrl = getBaseFaviconUrl();
   faviconUrl.searchParams.set('size', size);
-  faviconUrl.searchParams.set('page_url', url);
-  // TODO(dbeam): use the presence of 'allow_google_server_fallback' to
+  faviconUrl.searchParams.set('pageUrl', url);
+  // TODO(dbeam): use the presence of 'allowGoogleServerFallback' to
   // indicate true, otherwise false.
   const fallback = isSyncedUrlForHistoryUi ? '1' : '0';
-  faviconUrl.searchParams.set('allow_google_server_fallback', fallback);
+  faviconUrl.searchParams.set('allowGoogleServerFallback', fallback);
   if (isSyncedUrlForHistoryUi) {
-    faviconUrl.searchParams.set('icon_url', remoteIconUrlForUma);
+    faviconUrl.searchParams.set('iconUrl', remoteIconUrlForUma);
   }
 
   return getImageSet(faviconUrl.toString());
diff --git a/url/BUILD.gn b/url/BUILD.gn
index 056c74f..0a488519 100644
--- a/url/BUILD.gn
+++ b/url/BUILD.gn
@@ -309,9 +309,7 @@
 
   # Unlike gurl_junit_test_support targets depending on gurl_junit_shadows must
   # bypass platform checks.
-  android_library("gurl_junit_shadows") {
-    # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-    bypass_platform_checks = true
+  robolectric_library("gurl_junit_shadows") {
     testonly = true
     sources = [ "android/test/java/src/org/chromium/url/ShadowGURL.java" ]
     deps = [
@@ -353,9 +351,7 @@
         [ "android/javatests/src/org/chromium/url/GURLJavaTestHelper.java" ]
   }
 
-  android_library("gurl_junit_tests") {
-    # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-    bypass_platform_checks = true
+  robolectric_library("gurl_junit_tests") {
     testonly = true
     sources = [ "android/junit/src/org/chromium/url/ShadowGURLTest.java" ]
     deps = [
diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn
index b4a9e683..1a534bcd 100644
--- a/weblayer/browser/java/BUILD.gn
+++ b/weblayer/browser/java/BUILD.gn
@@ -408,9 +408,7 @@
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 }
 
-android_library("junit_test_support") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
+robolectric_library("junit_test_support") {
   testonly = true
   deps = [
     ":java",
@@ -434,8 +432,6 @@
 }
 
 junit_binary("weblayer_junit_tests") {
-  # Platform checks are broken for Robolectric. See https://crbug.com/1071638.
-  bypass_platform_checks = true
   testonly = true
   sources = [ "org/chromium/weblayer_private/payments/WebLayerPaymentRequestServiceTest.java" ]
   resources_package = "org.chromium.weblayer_private.test"